work on fixing some core tests

This commit is contained in:
Evan Almloff committed 2024-01-10 19:21:15 -06:00
1 parent 4a1a00b0f0
commit 55f76fede6
35 files changed
+422 -460

No files matched your search

+2
View File
@@ -33,6 +33,7 @@ serde = { version = "1", features = ["derive"], optional = true }
[dev-dependencies]
tokio = { workspace = true, features = ["full"] }
dioxus = { workspace = true }
dioxus-core = { workspace = true, features = ["internal-testing"] }
dioxus-html = { workspace = true, features = ["serialize"] }
pretty_assertions = "1.3.0"
rand = "0.8.5"
@@ -42,3 +43,4 @@ trybuild = "1.0"
[features]
default = []
serialize = ["serde"]
internal-testing = []
+1
View File
@@ -326,6 +326,7 @@ pub enum Mutation {
}
/// A static list of mutations that can be applied to the DOM. Note: this list does not contain any `Any` attribute values
#[derive(Debug, PartialEq, Default)]
pub struct MutationsVec {
/// The list of Scopes that were diffed, created, and removed during the Diff process.
pub dirty_scopes: FxHashSet<ScopeId>,
+1 -1
View File
@@ -10,7 +10,7 @@ use std::{cell::Ref, fmt::Debug, rc::Rc};
/// time for any logic that relies on these IDs to properly update.
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
pub struct ScopeId(pub(crate) usize);
pub struct ScopeId(pub usize);
impl ScopeId {
/// The root ScopeId.
+29 -2
View File
@@ -13,7 +13,7 @@ use crate::{
nodes::{Template, TemplateId},
runtime::{Runtime, RuntimeGuard},
scopes::{ScopeId, ScopeState},
AttributeValue, Element, Event,
AttributeValue, Element, Event, MutationsVec,
};
use futures_util::{pin_mut, StreamExt};
use rustc_hash::{FxHashMap, FxHashSet};
@@ -300,7 +300,7 @@ impl VirtualDom {
/// Get the single scope at the top of the VirtualDom tree that will always be around
///
/// This scope has a ScopeId of 0 and is the root of the tree
pub(crate) fn base_scope(&self) -> &ScopeState {
pub fn base_scope(&self) -> &ScopeState {
self.get_scope(ScopeId::ROOT).unwrap()
}
@@ -563,6 +563,14 @@ impl VirtualDom {
to.append_children(ElementId(0), m);
}
#[cfg(features = "internal-testing")]
/// [`VirtualDom::rebuild`] to a vector of mutations for testing purposes
pub fn rebuild_to_vec(&mut self) -> MutationsVec {
let mut mutations = MutationsVec::default();
self.rebuild(&mut mutations);
mutations
}
/// Render whatever the VirtualDom has ready as fast as possible without requiring an executor to progress
/// suspended subtrees.
pub fn render_immediate(&mut self, to: &mut impl WriteMutations) {
@@ -582,6 +590,14 @@ impl VirtualDom {
}
}
#[cfg(features = "internal-testing")]
/// [`Self::render_immediate`] to a vector of mutations for testing purposes
pub fn render_immediate_to_vec(&mut self) -> MutationsVec {
let mut mutations = MutationsVec::default();
self.render_immediate(&mut mutations);
mutations
}
/// Render the virtual dom, waiting for all suspense to be finished
///
/// The mutations will be thrown out, so it's best to use this method for things like SSR that have async content
@@ -646,6 +662,17 @@ impl VirtualDom {
}
}
#[cfg(features = "internal-testing")]
/// [`Self::render_with_deadline`] to a vector of mutations for testing purposes
pub async fn render_with_deadline_to_vec(
&mut self,
deadline: impl Future<Output = ()>,
) -> MutationsVec {
let mut mutations = MutationsVec::default();
self.render_with_deadline(deadline, &mut mutations).await;
mutations
}
/// Get the current runtime
pub fn runtime(&self) -> Rc<Runtime> {
self.runtime.clone()
+1 -1
View File
@@ -44,5 +44,5 @@ Hooks
VirtualDOM API
- [] work
- [] rebuild
- [] rebuild_to_vec
- [] change props
+11 -15
View File
@@ -10,16 +10,12 @@ use dioxus_core::BorrowedAttributeValue;
#[test]
fn attrs_cycle() {
let mut dom = VirtualDom::new(|cx| {
let id = cx.generation();
match cx.generation() % 2 {
0 => cx.render(rsx! {
div {}
}),
1 => cx.render(rsx! {
div {
h1 { class: "{id}", id: "{id}" }
}
}),
let id = generation();
match generation() % 2 {
0 => render! { div {} },
1 => render! {
div { h1 { class: "{id}", id: "{id}" } }
},
_ => unreachable!(),
}
});
@@ -27,7 +23,7 @@ fn attrs_cycle() {
let bump = Bump::new();
assert_eq!(
dom.rebuild().santize().edits,
dom.rebuild_to_vec_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
AppendChildren { m: 1, id: ElementId(0) },
@@ -36,7 +32,7 @@ fn attrs_cycle() {
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
AssignId { path: &[0,], id: ElementId(3,) },
@@ -58,7 +54,7 @@ fn attrs_cycle() {
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(1) },
ReplaceWith { id: ElementId(2), m: 1 }
@@ -67,7 +63,7 @@ fn attrs_cycle() {
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(2) },
AssignId { path: &[0], id: ElementId(3) },
@@ -90,7 +86,7 @@ fn attrs_cycle() {
// we take the node taken by attributes since we reused it
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(1) },
ReplaceWith { id: ElementId(2), m: 1 }
+3 -3
View File
@@ -4,16 +4,16 @@ use dioxus::prelude::*;
#[test]
fn bool_test() {
let mut app = VirtualDom::new(|cx| cx.render(rsx!(div { hidden: false })));
let mut app = VirtualDom::new(|cx| render!(div { hidden: false })));
let bump = Bump::new();
assert_eq!(
app.rebuild().santize().edits,
app.rebuild_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(1) },
SetAttribute {
name: "hidden",
value: (&*bump.alloc(false.into_value(&bump))).into(),
value: dioxus_core::AttributeValue::Bool(false),
id: ElementId(1,),
ns: None
},
+8 -10
View File
@@ -8,12 +8,12 @@ fn test_borrowed_state() {
let mut dom = VirtualDom::new(Parent);
assert_eq!(
dom.rebuild().santize().edits,
dom.rebuild_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
LoadTemplate { name: "template", index: 0, id: ElementId(3,) },
HydrateText { path: &[0,], value: "Hello w1!", id: ElementId(4,) },
HydrateText { path: &[0,], value: "Hello w1!".to_string(), id: ElementId(4,) },
ReplacePlaceholder { path: &[1,], m: 1 },
ReplacePlaceholder { path: &[0,], m: 1 },
AppendChildren { m: 1, id: ElementId(0) },
@@ -24,11 +24,9 @@ fn test_borrowed_state() {
fn Parent(cx: Scope) -> Element {
let w1 = cx.use_hook(|| String::from("w1"));
cx.render(rsx! {
div {
Child { name: w1 }
}
})
render! {
div { Child { name: w1 } }
}
}
#[derive(Props)]
@@ -37,12 +35,12 @@ struct ChildProps<'a> {
}
fn Child<'a>(cx: Scope<'a, ChildProps<'a>>) -> Element {
cx.render(rsx! {
render! {
div {
h1 { "it's nested" }
Child2 { name: cx.props.name }
}
})
}
}
#[derive(Props)]
@@ -51,5 +49,5 @@ struct Grandchild<'a> {
}
fn Child2<'a>(cx: Scope<'a, Grandchild<'a>>) -> Element {
cx.render(rsx!(div { "Hello {cx.props.name}!" }))
render!( div { "Hello {cx.props.name}!" } )
}
+4 -6
View File
@@ -3,7 +3,7 @@
use dioxus::prelude::*;
fn app(cx: Scope) -> Element {
let raw = match cx.generation() % 2 {
let raw = match generation() % 2 {
0 => "123.123",
1 => "123.123.123",
_ => unreachable!(),
@@ -11,9 +11,7 @@ fn app(cx: Scope) -> Element {
let value = raw.parse::<f32>().unwrap_or(123.123);
cx.render(rsx! {
div { "hello {value}" }
})
render! { div { "hello {value}" } }
}
#[test]
@@ -21,10 +19,10 @@ fn bubbles_error() {
let mut dom = VirtualDom::new(app);
{
let _edits = dom.rebuild().santize();
let _edits = dom.rebuild_to_vec().santize();
}
dom.mark_dirty(ScopeId::ROOT);
_ = dom.render_immediate();
_ = dom.render_immediate_to_vec();
}
+12 -12
View File
@@ -4,48 +4,48 @@ use dioxus::prelude::*;
#[test]
fn state_shares() {
fn app(cx: Scope) -> Element {
cx.provide_context(cx.generation() as i32);
cx.provide_context(generation() as i32);
cx.render(rsx!(child_1 {}))
render!(child_1 {})
}
fn child_1(cx: Scope) -> Element {
cx.render(rsx!(child_2 {}))
render!(child_2 {})
}
fn child_2(cx: Scope) -> Element {
let value = cx.consume_context::<i32>().unwrap();
cx.render(rsx!("Value is {value}"))
render!("Value is {value}")
}
let mut dom = VirtualDom::new(app);
assert_eq!(
dom.rebuild().santize().edits,
dom.rebuild_to_vec().santize().edits,
[
CreateTextNode { value: "Value is 0", id: ElementId(1,) },
CreateTextNode { value: "Value is 0".to_string(), id: ElementId(1,) },
AppendChildren { m: 1, id: ElementId(0) },
]
);
dom.mark_dirty(ScopeId::ROOT);
_ = dom.render_immediate();
_ = dom.render_immediate_to_vec();
assert_eq!(dom.base_scope().consume_context::<i32>().unwrap(), 1);
dom.mark_dirty(ScopeId::ROOT);
_ = dom.render_immediate();
_ = dom.render_immediate_to_vec();
assert_eq!(dom.base_scope().consume_context::<i32>().unwrap(), 2);
dom.mark_dirty(ScopeId(2));
assert_eq!(
dom.render_immediate().santize().edits,
[SetText { value: "Value is 2", id: ElementId(1,) },]
dom.render_immediate_to_vec().santize().edits,
[SetText { value: "Value is 2".to_string(), id: ElementId(1,) },]
);
dom.mark_dirty(ScopeId::ROOT);
dom.mark_dirty(ScopeId(2));
let edits = dom.render_immediate();
let edits = dom.render_immediate_to_vec();
assert_eq!(
edits.santize().edits,
[SetText { value: "Value is 3", id: ElementId(1,) },]
[SetText { value: "Value is 3".to_string(), id: ElementId(1,) },]
);
}
+25 -36
View File
@@ -2,8 +2,8 @@
//! Prove that the dom works normally through virtualdom methods.
//!
//! This methods all use "rebuild" which completely bypasses the scheduler.
//! Hard rebuilds don't consume any events from the event queue.
//! This methods all use "rebuild_to_vec" which completely bypasses the scheduler.
//! Hard rebuild_to_vecs don't consume any events from the event queue.
use dioxus::core::Mutation::*;
use dioxus::prelude::*;
@@ -12,16 +12,12 @@ use dioxus_core::ElementId;
#[test]
fn test_original_diff() {
let mut dom = VirtualDom::new(|cx| {
cx.render(rsx! {
div {
div {
"Hello, world!"
}
}
})
render! {
div { div { "Hello, world!" } }
}
});
let edits = dom.rebuild().santize();
let edits = dom.rebuild_to_vec().santize();
assert_eq!(
edits.edits,
@@ -36,24 +32,21 @@ fn test_original_diff() {
#[test]
fn create() {
let mut dom = VirtualDom::new(|cx| {
cx.render(rsx! {
render! {
div {
div {
"Hello, world!"
div {
div {
Fragment {
"hello"
"world"
}
Fragment { "hello""world" }
}
}
}
}
})
}
});
let _edits = dom.rebuild().santize();
let _edits = dom.rebuild_to_vec().santize();
// todo: we don't test template mutations anymore since the templates are passed along
@@ -82,13 +75,9 @@ fn create() {
#[test]
fn create_list() {
let mut dom = VirtualDom::new(|cx| {
cx.render(rsx! {
(0..3).map(|f| rsx!( div { "hello" } ))
})
});
let mut dom = VirtualDom::new(|cx| render! {(0..3).map(|f| render!( div { "hello" } ))}));
let _edits = dom.rebuild().santize();
let _edits = dom.rebuild_to_vec().santize();
// note: we dont test template edits anymore
// assert_eq!(
@@ -106,15 +95,15 @@ fn create_list() {
#[test]
fn create_simple() {
let mut dom = VirtualDom::new(|cx| {
cx.render(rsx! {
render! {
div {}
div {}
div {}
div {}
})
}
});
let edits = dom.rebuild().santize();
let edits = dom.rebuild_to_vec().santize();
// note: we dont test template edits anymore
// assert_eq!(
@@ -133,11 +122,11 @@ fn create_simple() {
#[test]
fn create_components() {
let mut dom = VirtualDom::new(|cx| {
cx.render(rsx! {
render! {
Child { "abc1" }
Child { "abc2" }
Child { "abc3" }
})
}
});
#[derive(Props)]
@@ -146,14 +135,14 @@ fn create_components() {
}
fn Child<'a>(cx: Scope<'a, ChildProps<'a>>) -> Element {
cx.render(rsx! {
render! {
h1 {}
div { &cx.props.children }
p {}
})
}
}
let _edits = dom.rebuild().santize();
let _edits = dom.rebuild_to_vec().santize();
// todo: test this
}
@@ -161,18 +150,18 @@ fn create_components() {
#[test]
fn anchors() {
let mut dom = VirtualDom::new(|cx| {
cx.render(rsx! {
render! {
if true {
rsx!( div { "hello" } )
render!( div { "hello" } )
}
if false {
rsx!( div { "goodbye" } )
render!( div { "goodbye" } )
}
})
}
});
// note that the template under "false" doesn't show up since it's not loaded
let edits = dom.rebuild().santize();
let edits = dom.rebuild_to_vec().santize();
// note: we dont test template edits anymore
// assert_eq!(
+4 -4
View File
@@ -4,18 +4,18 @@ use dioxus::prelude::*;
#[test]
fn multiroot() {
let mut dom = VirtualDom::new(|cx| {
cx.render(rsx! {
render! {
div { "Hello a" }
div { "Hello b" }
div { "Hello c" }
})
}
});
// note: we dont test template edits anymore
let _templates = dom.rebuild().santize().templates;
let _templates = dom.rebuild_to_vec().santize().templates;
// assert_eq!(
// dom.rebuild().santize().templates,
// dom.rebuild_to_vec().santize().templates,
// [
// CreateElement { name: "div" },
// CreateStaticText { value: "Hello a" },
+20 -23
View File
@@ -7,11 +7,11 @@ use dioxus_core::ElementId;
#[test]
fn empty_fragment_creates_nothing() {
fn app(cx: Scope) -> Element {
cx.render(rsx!(()))
render!(())
}
let mut vdom = VirtualDom::new(app);
let edits = vdom.rebuild();
let edits = vdom.rebuild_to_vec();
assert_eq!(
edits.edits,
@@ -25,14 +25,14 @@ fn empty_fragment_creates_nothing() {
#[test]
fn root_fragments_work() {
let mut vdom = VirtualDom::new(|cx| {
cx.render(rsx!(
render!(
div { "hello" }
div { "goodbye" }
))
)
});
assert_eq!(
vdom.rebuild().edits.last().unwrap(),
vdom.rebuild_to_vec().edits.last().unwrap(),
&AppendChildren { id: ElementId(0), m: 2 }
);
}
@@ -40,26 +40,26 @@ fn root_fragments_work() {
#[test]
fn fragments_nested() {
let mut vdom = VirtualDom::new(|cx| {
cx.render(rsx!(
render!(
div { "hello" }
div { "goodbye" }
rsx! {
render! {
div { "hello" }
div { "goodbye" }
rsx! {
render! {
div { "hello" }
div { "goodbye" }
rsx! {
render! {
div { "hello" }
div { "goodbye" }
}
}
}
))
)
});
assert_eq!(
vdom.rebuild().edits.last().unwrap(),
vdom.rebuild_to_vec().edits.last().unwrap(),
&AppendChildren { id: ElementId(0), m: 8 }
);
}
@@ -67,24 +67,21 @@ fn fragments_nested() {
#[test]
fn fragments_across_components() {
fn app(cx: Scope) -> Element {
cx.render(rsx! {
render! {
demo_child {}
demo_child {}
demo_child {}
demo_child {}
})
}
}
fn demo_child(cx: Scope) -> Element {
let world = "world";
cx.render(rsx! {
"hellO!"
world
})
render! { "hellO!", world }
}
assert_eq!(
VirtualDom::new(app).rebuild().edits.last().unwrap(),
VirtualDom::new(app).rebuild_to_vec().edits.last().unwrap(),
&AppendChildren { id: ElementId(0), m: 8 }
);
}
@@ -92,13 +89,13 @@ fn fragments_across_components() {
#[test]
fn list_fragments() {
fn app(cx: Scope) -> Element {
cx.render(rsx!(
h1 {"hello"}
(0..6).map(|f| rsx!( span { "{f}" }))
))
render!(
h1 { "hello" }
(0..6).map(|f| render!( span { "{f}" }))
)
}
assert_eq!(
VirtualDom::new(app).rebuild().edits.last().unwrap(),
VirtualDom::new(app).rebuild_to_vec().edits.last().unwrap(),
&AppendChildren { id: ElementId(0), m: 7 }
);
}
+8 -8
View File
@@ -5,27 +5,27 @@ use dioxus_core::ElementId;
// A real-world usecase of templates at peak performance
// In react, this would be a lot of node creation.
//
// In Dioxus, we memoize the rsx! body and simplify it down to a few template loads
// In Dioxus, we memoize the render! body and simplify it down to a few template loads
//
// Also note that the IDs increase linearly. This lets us drive a vec on the renderer for O(1) re-indexing
fn app(cx: Scope) -> Element {
cx.render(rsx! {
render! {
div {
(0..3).map(|i| rsx! {
(0..3).map(|i| render! {
div {
h1 { "hello world! "}
p { "{i}" }
}
})
}
})
}
}
#[test]
fn list_renders() {
let mut dom = VirtualDom::new(app);
let edits = dom.rebuild().santize();
let edits = dom.rebuild_to_vec().santize();
// note: we dont test template edits anymore
// assert_eq!(
@@ -58,11 +58,11 @@ fn list_renders() {
LoadTemplate { name: "template", index: 0, id: ElementId(1) },
// Load each template one-by-one, rehydrating it
LoadTemplate { name: "template", index: 0, id: ElementId(2) },
HydrateText { path: &[1, 0], value: "0", id: ElementId(3) },
HydrateText { path: &[1, 0], value: "0".to_string(), id: ElementId(3) },
LoadTemplate { name: "template", index: 0, id: ElementId(4) },
HydrateText { path: &[1, 0], value: "1", id: ElementId(5) },
HydrateText { path: &[1, 0], value: "1".to_string(), id: ElementId(5) },
LoadTemplate { name: "template", index: 0, id: ElementId(6) },
HydrateText { path: &[1, 0], value: "2", id: ElementId(7) },
HydrateText { path: &[1, 0], value: "2".to_string(), id: ElementId(7) },
// Replace the 0th childn on the div with the 3 templates on the stack
ReplacePlaceholder { m: 3, path: &[0] },
// Append the container div to the dom
+14 -18
View File
@@ -7,24 +7,22 @@ use dioxus_core::ElementId;
fn nested_passthru_creates() {
#[component]
fn App(cx: Scope) -> Element {
cx.render(rsx! {
render! {
PassThru {
PassThru {
PassThru {
div { "hi" }
}
PassThru { div { "hi" } }
}
}
})
}
}
#[component]
fn PassThru<'a>(cx: Scope<'a>, children: Element) -> Element {
cx.render(rsx!(children))
render!(children)
}
let mut dom = VirtualDom::new(App);
let edits = dom.rebuild().santize();
let edits = dom.rebuild_to_vec().santize();
assert_eq!(
edits.edits,
@@ -42,31 +40,29 @@ fn nested_passthru_creates() {
fn nested_passthru_creates_add() {
#[component]
fn App(cx: Scope) -> Element {
cx.render(rsx! {
render! {
ChildComp {
"1"
ChildComp {
"2"
ChildComp {
"3"
div {
"hi"
}
div { "hi" }
}
}
}
})
}
}
#[component]
fn ChildComp<'a>(cx: Scope, children: Element) -> Element {
cx.render(rsx! { children })
render! {children}
}
let mut dom = VirtualDom::new(App);
assert_eq!(
dom.rebuild().santize().edits,
dom.rebuild_to_vec().santize().edits,
[
// load 1
LoadTemplate { name: "template", index: 0, id: ElementId(1) },
@@ -88,11 +84,11 @@ fn dynamic_node_as_root() {
fn App(cx: Scope) -> Element {
let a = 123;
let b = 456;
cx.render(rsx! { "{a}" "{b}" })
render! { "{a}", "{b}" }
}
let mut dom = VirtualDom::new(App);
let edits = dom.rebuild().santize();
let edits = dom.rebuild_to_vec().santize();
// Since the roots were all dynamic, they should not cause any template muations
assert!(edits.templates.is_empty());
@@ -101,8 +97,8 @@ fn dynamic_node_as_root() {
assert_eq!(
edits.edits,
[
CreateTextNode { value: "123", id: ElementId(1) },
CreateTextNode { value: "456", id: ElementId(2) },
CreateTextNode { value: "123".to_string(), id: ElementId(1) },
CreateTextNode { value: "456".to_string(), id: ElementId(2) },
AppendChildren { id: ElementId(0), m: 2 }
]
)
+8 -10
View File
@@ -4,16 +4,14 @@ 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 mut dom = VirtualDom::new(|cx| match generation() % 2 {
0 => render! { div { "wasd" } },
1 => render! { div { "abcd" } },
_ => unreachable!(),
});
{
let edits = dom.rebuild().santize();
let edits = dom.rebuild_to_vec().santize();
assert_eq!(
edits.edits,
[
@@ -25,7 +23,7 @@ fn cycling_elements() {
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
ReplaceWith { id: ElementId(1,), m: 1 },
@@ -35,7 +33,7 @@ fn cycling_elements() {
// notice that the IDs cycle back to ElementId(1), preserving a minimal memory footprint
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
ReplaceWith { id: ElementId(2,), m: 1 },
@@ -44,7 +42,7 @@ fn cycling_elements() {
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
ReplaceWith { id: ElementId(1,), m: 1 },
+18 -21
View File
@@ -12,55 +12,52 @@ fn component_swap() {
*render_phase += 1;
cx.render(match *render_phase {
0 => rsx! {
match *render_phase {
0 => render! {
nav_bar {}
dash_board {}
},
1 => rsx! {
1 => render! {
nav_bar {}
dash_results {}
},
2 => rsx! {
2 => render! {
nav_bar {}
dash_board {}
},
3 => rsx! {
3 => render! {
nav_bar {}
dash_results {}
},
4 => rsx! {
4 => render! {
nav_bar {}
dash_board {}
},
_ => rsx!("blah"),
})
_ => render!("blah"),
}
}
fn nav_bar(cx: Scope) -> Element {
cx.render(rsx! {
h1 {
"NavBar"
(0..3).map(|_| rsx!(nav_link {}))
}
})
render! {
h1 { "NavBar", (0..3).map(|_| render!(nav_link {})) }
}
}
fn nav_link(cx: Scope) -> Element {
cx.render(rsx!( h1 { "nav_link" } ))
render!( h1 { "nav_link" } )
}
fn dash_board(cx: Scope) -> Element {
cx.render(rsx!( div { "dashboard" } ))
render!( div { "dashboard" } )
}
fn dash_results(cx: Scope) -> Element {
cx.render(rsx!( div { "results" } ))
render!( div { "results" } )
}
let mut dom = VirtualDom::new(app);
{
let edits = dom.rebuild().santize();
let edits = dom.rebuild_to_vec().santize();
assert_eq!(
edits.edits,
[
@@ -77,7 +74,7 @@ fn component_swap() {
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(6) },
ReplaceWith { id: ElementId(5), m: 1 }
@@ -86,7 +83,7 @@ fn component_swap() {
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(5) },
ReplaceWith { id: ElementId(6), m: 1 }
@@ -95,7 +92,7 @@ fn component_swap() {
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(6) },
ReplaceWith { id: ElementId(5), m: 1 }
+17 -17
View File
@@ -5,50 +5,50 @@ use dioxus_core::ElementId;
#[test]
fn text_diff() {
fn app(cx: Scope) -> Element {
let gen = cx.generation();
cx.render(rsx!( h1 { "hello {gen}" } ))
let gen = generation();
render!( h1 { "hello {gen}" } )
}
let mut vdom = VirtualDom::new(app);
_ = vdom.rebuild();
_ = vdom.rebuild_to_vec();
vdom.mark_dirty(ScopeId::ROOT);
assert_eq!(
vdom.render_immediate().edits,
[SetText { value: "hello 1", id: ElementId(2) }]
vdom.render_immediate_to_vec().edits,
[SetText { value: "hello 1".to_string(), id: ElementId(2) }]
);
vdom.mark_dirty(ScopeId::ROOT);
assert_eq!(
vdom.render_immediate().edits,
[SetText { value: "hello 2", id: ElementId(2) }]
vdom.render_immediate_to_vec().edits,
[SetText { value: "hello 2".to_string(), id: ElementId(2) }]
);
vdom.mark_dirty(ScopeId::ROOT);
assert_eq!(
vdom.render_immediate().edits,
[SetText { value: "hello 3", id: ElementId(2) }]
vdom.render_immediate_to_vec().edits,
[SetText { value: "hello 3".to_string(), id: ElementId(2) }]
);
}
#[test]
fn element_swap() {
fn app(cx: Scope) -> Element {
let gen = cx.generation();
let gen = generation();
match gen % 2 {
0 => cx.render(rsx!( h1 { "hello 1" } )),
1 => cx.render(rsx!( h2 { "hello 2" } )),
0 => render!( h1 { "hello 1" } ),
1 => render!( h2 { "hello 2" } ),
_ => unreachable!(),
}
}
let mut vdom = VirtualDom::new(app);
_ = vdom.rebuild();
_ = vdom.rebuild_to_vec();
vdom.mark_dirty(ScopeId::ROOT);
assert_eq!(
vdom.render_immediate().santize().edits,
vdom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
ReplaceWith { id: ElementId(1,), m: 1 },
@@ -57,7 +57,7 @@ fn element_swap() {
vdom.mark_dirty(ScopeId::ROOT);
assert_eq!(
vdom.render_immediate().santize().edits,
vdom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
ReplaceWith { id: ElementId(2,), m: 1 },
@@ -66,7 +66,7 @@ fn element_swap() {
vdom.mark_dirty(ScopeId::ROOT);
assert_eq!(
vdom.render_immediate().santize().edits,
vdom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
ReplaceWith { id: ElementId(1,), m: 1 },
@@ -75,7 +75,7 @@ fn element_swap() {
vdom.mark_dirty(ScopeId::ROOT);
assert_eq!(
vdom.render_immediate().santize().edits,
vdom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
ReplaceWith { id: ElementId(2,), m: 1 },
+48 -48
View File
@@ -11,18 +11,18 @@ use dioxus::prelude::*;
#[test]
fn keyed_diffing_out_of_order() {
let mut dom = VirtualDom::new(|cx| {
let order = match cx.generation() % 2 {
let order = match generation() % 2 {
0 => &[0, 1, 2, 3, /**/ 4, 5, 6, /**/ 7, 8, 9],
1 => &[0, 1, 2, 3, /**/ 6, 4, 5, /**/ 7, 8, 9],
_ => unreachable!(),
};
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
render!(order.iter().map(|i| render!(div { key: "{i}" })))
});
{
assert_eq!(
dom.rebuild().santize().edits,
dom.rebuild_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
@@ -41,7 +41,7 @@ fn keyed_diffing_out_of_order() {
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().edits,
dom.render_immediate_to_vec().edits,
[
PushRoot { id: ElementId(7,) },
InsertBefore { id: ElementId(5,), m: 1 },
@@ -53,20 +53,20 @@ fn keyed_diffing_out_of_order() {
#[test]
fn keyed_diffing_out_of_order_adds() {
let mut dom = VirtualDom::new(|cx| {
let order = match cx.generation() % 2 {
let order = match generation() % 2 {
0 => &[/**/ 4, 5, 6, 7, 8 /**/],
1 => &[/**/ 8, 7, 4, 5, 6 /**/],
_ => unreachable!(),
};
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
render!(order.iter().map(|i| render!(div { key: "{i}" })))
});
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().edits,
dom.render_immediate_to_vec().edits,
[
PushRoot { id: ElementId(5,) },
PushRoot { id: ElementId(4,) },
@@ -79,20 +79,20 @@ fn keyed_diffing_out_of_order_adds() {
#[test]
fn keyed_diffing_out_of_order_adds_3() {
let mut dom = VirtualDom::new(|cx| {
let order = match cx.generation() % 2 {
let order = match generation() % 2 {
0 => &[/**/ 4, 5, 6, 7, 8 /**/],
1 => &[/**/ 4, 8, 7, 5, 6 /**/],
_ => unreachable!(),
};
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
render!(order.iter().map(|i| render!(div { key: "{i}" })))
});
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().edits,
dom.render_immediate_to_vec().edits,
[
PushRoot { id: ElementId(5,) },
PushRoot { id: ElementId(4,) },
@@ -105,20 +105,20 @@ fn keyed_diffing_out_of_order_adds_3() {
#[test]
fn keyed_diffing_out_of_order_adds_4() {
let mut dom = VirtualDom::new(|cx| {
let order = match cx.generation() % 2 {
let order = match generation() % 2 {
0 => &[/**/ 4, 5, 6, 7, 8 /**/],
1 => &[/**/ 4, 5, 8, 7, 6 /**/],
_ => unreachable!(),
};
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
render!(order.iter().map(|i| render!(div { key: "{i}" })))
});
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().edits,
dom.render_immediate_to_vec().edits,
[
PushRoot { id: ElementId(5,) },
PushRoot { id: ElementId(4,) },
@@ -131,20 +131,20 @@ fn keyed_diffing_out_of_order_adds_4() {
#[test]
fn keyed_diffing_out_of_order_adds_5() {
let mut dom = VirtualDom::new(|cx| {
let order = match cx.generation() % 2 {
let order = match generation() % 2 {
0 => &[/**/ 4, 5, 6, 7, 8 /**/],
1 => &[/**/ 4, 5, 6, 8, 7 /**/],
_ => unreachable!(),
};
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
render!(order.iter().map(|i| render!(div { key: "{i}" })))
});
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().edits,
dom.render_immediate_to_vec().edits,
[
PushRoot { id: ElementId(5,) },
InsertBefore { id: ElementId(4,), m: 1 },
@@ -156,20 +156,20 @@ fn keyed_diffing_out_of_order_adds_5() {
#[test]
fn keyed_diffing_additions() {
let mut dom = VirtualDom::new(|cx| {
let order: &[_] = match cx.generation() % 2 {
let order: &[_] = match generation() % 2 {
0 => &[/**/ 4, 5, 6, 7, 8 /**/],
1 => &[/**/ 4, 5, 6, 7, 8, 9, 10 /**/],
_ => unreachable!(),
};
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
render!(order.iter().map(|i| render!(div { key: "{i}" })))
});
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(6) },
LoadTemplate { name: "template", index: 0, id: ElementId(7) },
@@ -181,20 +181,20 @@ fn keyed_diffing_additions() {
#[test]
fn keyed_diffing_additions_and_moves_on_ends() {
let mut dom = VirtualDom::new(|cx| {
let order: &[_] = match cx.generation() % 2 {
let order: &[_] = match generation() % 2 {
0 => &[/**/ 4, 5, 6, 7 /**/],
1 => &[/**/ 7, 4, 5, 6, 11, 12 /**/],
_ => unreachable!(),
};
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
render!(order.iter().map(|i| render!(div { key: "{i}" })))
});
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
// create 11, 12
LoadTemplate { name: "template", index: 0, id: ElementId(5) },
@@ -210,21 +210,21 @@ fn keyed_diffing_additions_and_moves_on_ends() {
#[test]
fn keyed_diffing_additions_and_moves_in_middle() {
let mut dom = VirtualDom::new(|cx| {
let order: &[_] = match cx.generation() % 2 {
let order: &[_] = match generation() % 2 {
0 => &[/**/ 1, 2, 3, 4 /**/],
1 => &[/**/ 4, 1, 7, 8, 2, 5, 6, 3 /**/],
_ => unreachable!(),
};
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
render!(order.iter().map(|i| render!(div { key: "{i}" })))
});
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
// LIS: 4, 5, 6
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
// create 5, 6
LoadTemplate { name: "template", index: 0, id: ElementId(5) },
@@ -244,21 +244,21 @@ fn keyed_diffing_additions_and_moves_in_middle() {
#[test]
fn controlled_keyed_diffing_out_of_order() {
let mut dom = VirtualDom::new(|cx| {
let order: &[_] = match cx.generation() % 2 {
let order: &[_] = match generation() % 2 {
0 => &[4, 5, 6, 7],
1 => &[0, 5, 9, 6, 4],
_ => unreachable!(),
};
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
render!(order.iter().map(|i| render!(div { key: "{i}" })))
});
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
// LIS: 5, 6
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
// remove 7
Remove { id: ElementId(4,) },
@@ -278,20 +278,20 @@ fn controlled_keyed_diffing_out_of_order() {
#[test]
fn controlled_keyed_diffing_out_of_order_max_test() {
let mut dom = VirtualDom::new(|cx| {
let order: &[_] = match cx.generation() % 2 {
let order: &[_] = match generation() % 2 {
0 => &[0, 1, 2, 3, 4],
1 => &[3, 0, 1, 10, 2],
_ => unreachable!(),
};
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
render!(order.iter().map(|i| render!(div { key: "{i}" })))
});
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
Remove { id: ElementId(5,) },
LoadTemplate { name: "template", index: 0, id: ElementId(5) },
@@ -307,20 +307,20 @@ fn controlled_keyed_diffing_out_of_order_max_test() {
#[test]
fn remove_list() {
let mut dom = VirtualDom::new(|cx| {
let order: &[_] = match cx.generation() % 2 {
let order: &[_] = match generation() % 2 {
0 => &[9, 8, 7, 6, 5],
1 => &[9, 8],
_ => unreachable!(),
};
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
render!(order.iter().map(|i| render!(div { key: "{i}" })))
});
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
Remove { id: ElementId(5) },
Remove { id: ElementId(4) },
@@ -332,20 +332,20 @@ fn remove_list() {
#[test]
fn no_common_keys() {
let mut dom = VirtualDom::new(|cx| {
let order: &[_] = match cx.generation() % 2 {
let order: &[_] = match generation() % 2 {
0 => &[1, 2, 3],
1 => &[4, 5, 6],
_ => unreachable!(),
};
cx.render(rsx!(order.iter().map(|i| rsx!(div { key: "{i}" }))))
render!(order.iter().map(|i| render!(div { key: "{i}" })))
});
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
Remove { id: ElementId(3) },
Remove { id: ElementId(2) },
+78 -80
View File
@@ -5,20 +5,20 @@ use pretty_assertions::assert_eq;
#[test]
fn list_creates_one_by_one() {
let mut dom = VirtualDom::new(|cx| {
let gen = cx.generation();
let gen = generation();
cx.render(rsx! {
render! {
div {
(0..gen).map(|i| rsx! {
(0..gen).map(|i| render! {
div { "{i}" }
})
}
})
}
});
// load the div and then assign the empty fragment as a placeholder
assert_eq!(
dom.rebuild().santize().edits,
dom.rebuild_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
AssignId { path: &[0], id: ElementId(2,) },
@@ -29,10 +29,10 @@ fn list_creates_one_by_one() {
// Rendering the first item should replace the placeholder with an element
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(3,) },
HydrateText { path: &[0], value: "0", id: ElementId(4,) },
HydrateText { path: &[0], value: "0".to_string(), id: ElementId(4,) },
ReplaceWith { id: ElementId(2,), m: 1 },
]
);
@@ -40,10 +40,10 @@ fn list_creates_one_by_one() {
// Rendering the next item should insert after the previous
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
HydrateText { path: &[0], value: "1", id: ElementId(5,) },
HydrateText { path: &[0], value: "1".to_string(), id: ElementId(5,) },
InsertAfter { id: ElementId(3,), m: 1 },
]
);
@@ -51,10 +51,10 @@ fn list_creates_one_by_one() {
// ... and again!
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(6,) },
HydrateText { path: &[0], value: "2", id: ElementId(7,) },
HydrateText { path: &[0], value: "2".to_string(), id: ElementId(7,) },
InsertAfter { id: ElementId(2,), m: 1 },
]
);
@@ -62,10 +62,10 @@ fn list_creates_one_by_one() {
// once more
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(8,) },
HydrateText { path: &[0], value: "3", id: ElementId(9,) },
HydrateText { path: &[0], value: "3".to_string(), id: ElementId(9,) },
InsertAfter { id: ElementId(6,), m: 1 },
]
);
@@ -74,30 +74,30 @@ fn list_creates_one_by_one() {
#[test]
fn removes_one_by_one() {
let mut dom = VirtualDom::new(|cx| {
let gen = 3 - cx.generation() % 4;
let gen = 3 - generation() % 4;
cx.render(rsx! {
render! {
div {
(0..gen).map(|i| rsx! {
(0..gen).map(|i| render! {
div { "{i}" }
})
}
})
}
});
// load the div and then assign the empty fragment as a placeholder
assert_eq!(
dom.rebuild().santize().edits,
dom.rebuild_to_vec().santize().edits,
[
// The container
LoadTemplate { name: "template", index: 0, id: ElementId(1) },
// each list item
LoadTemplate { name: "template", index: 0, id: ElementId(2) },
HydrateText { path: &[0], value: "0", id: ElementId(3) },
HydrateText { path: &[0], value: "0".to_string(), id: ElementId(3) },
LoadTemplate { name: "template", index: 0, id: ElementId(4) },
HydrateText { path: &[0], value: "1", id: ElementId(5) },
HydrateText { path: &[0], value: "1".to_string(), id: ElementId(5) },
LoadTemplate { name: "template", index: 0, id: ElementId(6) },
HydrateText { path: &[0], value: "2", id: ElementId(7) },
HydrateText { path: &[0], value: "2".to_string(), id: ElementId(7) },
// replace the placeholder in the template with the 3 templates on the stack
ReplacePlaceholder { m: 3, path: &[0] },
// Mount the div
@@ -109,14 +109,14 @@ fn removes_one_by_one() {
// Rendering the first item should replace the placeholder with an element
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[Remove { id: ElementId(6) }]
);
// Remove div(2)
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[Remove { id: ElementId(4) }]
);
@@ -124,7 +124,7 @@ fn removes_one_by_one() {
// todo: this should just be a remove with no placeholder
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
CreatePlaceholder { id: ElementId(4) },
ReplaceWith { id: ElementId(2), m: 1 }
@@ -135,14 +135,14 @@ fn removes_one_by_one() {
// todo: this should actually be append to, but replace placeholder is fine for now
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(2) },
HydrateText { path: &[0], value: "0", id: ElementId(3) },
HydrateText { path: &[0], value: "0".to_string(), id: ElementId(3) },
LoadTemplate { name: "template", index: 0, id: ElementId(5) },
HydrateText { path: &[0], value: "1", id: ElementId(6) },
HydrateText { path: &[0], value: "1".to_string(), id: ElementId(6) },
LoadTemplate { name: "template", index: 0, id: ElementId(7) },
HydrateText { path: &[0], value: "2", id: ElementId(8) },
HydrateText { path: &[0], value: "2".to_string(), id: ElementId(8) },
ReplaceWith { id: ElementId(4), m: 3 }
]
);
@@ -151,18 +151,18 @@ fn removes_one_by_one() {
#[test]
fn list_shrink_multiroot() {
let mut dom = VirtualDom::new(|cx| {
cx.render(rsx! {
render! {
div {
(0..cx.generation()).map(|i| rsx! {
(0..generation()).map(|i| render! {
div { "{i}" }
div { "{i}" }
})
}
})
}
});
assert_eq!(
dom.rebuild().santize().edits,
dom.rebuild_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
AssignId { path: &[0,], id: ElementId(2,) },
@@ -172,36 +172,36 @@ fn list_shrink_multiroot() {
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(3) },
HydrateText { path: &[0], value: "0", id: ElementId(4) },
HydrateText { path: &[0], value: "0".to_string(), id: ElementId(4) },
LoadTemplate { name: "template", index: 1, id: ElementId(5) },
HydrateText { path: &[0], value: "0", id: ElementId(6) },
HydrateText { path: &[0], value: "0".to_string(), id: ElementId(6) },
ReplaceWith { id: ElementId(2), m: 2 }
]
);
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(2) },
HydrateText { path: &[0], value: "1", id: ElementId(7) },
HydrateText { path: &[0], value: "1".to_string(), id: ElementId(7) },
LoadTemplate { name: "template", index: 1, id: ElementId(8) },
HydrateText { path: &[0], value: "1", id: ElementId(9) },
HydrateText { path: &[0], value: "1".to_string(), id: ElementId(9) },
InsertAfter { id: ElementId(5), m: 2 }
]
);
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(10) },
HydrateText { path: &[0], value: "2", id: ElementId(11) },
HydrateText { path: &[0], value: "2".to_string(), id: ElementId(11) },
LoadTemplate { name: "template", index: 1, id: ElementId(12) },
HydrateText { path: &[0], value: "2", id: ElementId(13) },
HydrateText { path: &[0], value: "2".to_string(), id: ElementId(13) },
InsertAfter { id: ElementId(8), m: 2 }
]
);
@@ -210,38 +210,38 @@ fn list_shrink_multiroot() {
#[test]
fn removes_one_by_one_multiroot() {
let mut dom = VirtualDom::new(|cx| {
let gen = 3 - cx.generation() % 4;
let gen = 3 - generation() % 4;
cx.render(rsx! {
render! {
div {
(0..gen).map(|i| rsx! {
(0..gen).map(|i| render! {
div { "{i}" }
div { "{i}" }
})
}
})
}
});
// load the div and then assign the empty fragment as a placeholder
assert_eq!(
dom.rebuild().santize().edits,
dom.rebuild_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(1) },
//
LoadTemplate { name: "template", index: 0, id: ElementId(2) },
HydrateText { path: &[0], value: "0", id: ElementId(3) },
HydrateText { path: &[0], value: "0".to_string(), id: ElementId(3) },
LoadTemplate { name: "template", index: 1, id: ElementId(4) },
HydrateText { path: &[0], value: "0", id: ElementId(5) },
HydrateText { path: &[0], value: "0".to_string(), id: ElementId(5) },
//
LoadTemplate { name: "template", index: 0, id: ElementId(6) },
HydrateText { path: &[0], value: "1", id: ElementId(7) },
HydrateText { path: &[0], value: "1".to_string(), id: ElementId(7) },
LoadTemplate { name: "template", index: 1, id: ElementId(8) },
HydrateText { path: &[0], value: "1", id: ElementId(9) },
HydrateText { path: &[0], value: "1".to_string(), id: ElementId(9) },
//
LoadTemplate { name: "template", index: 0, id: ElementId(10) },
HydrateText { path: &[0], value: "2", id: ElementId(11) },
HydrateText { path: &[0], value: "2".to_string(), id: ElementId(11) },
LoadTemplate { name: "template", index: 1, id: ElementId(12) },
HydrateText { path: &[0], value: "2", id: ElementId(13) },
HydrateText { path: &[0], value: "2".to_string(), id: ElementId(13) },
//
ReplacePlaceholder { path: &[0], m: 6 },
//
@@ -251,19 +251,19 @@ fn removes_one_by_one_multiroot() {
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[Remove { id: ElementId(10) }, Remove { id: ElementId(12) }]
);
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[Remove { id: ElementId(6) }, Remove { id: ElementId(8) }]
);
dom.mark_dirty(ScopeId::ROOT);
assert_eq!(
dom.render_immediate().santize().edits,
dom.render_immediate_to_vec().santize().edits,
[
CreatePlaceholder { id: ElementId(8) },
Remove { id: ElementId(2) },
@@ -275,48 +275,46 @@ fn removes_one_by_one_multiroot() {
#[test]
fn two_equal_fragments_are_equal_static() {
let mut dom = VirtualDom::new(|cx| {
cx.render(rsx! {
(0..5).map(|_| rsx! {
render! {
(0..5).map(|_| render! {
div { "hello" }
})
})
}
});
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert!(dom.render_immediate().edits.is_empty());
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
assert!(dom.render_immediate_to_vec().edits.is_empty());
}
#[test]
fn two_equal_fragments_are_equal() {
let mut dom = VirtualDom::new(|cx| {
cx.render(rsx! {
(0..5).map(|i| rsx! {
render! {
(0..5).map(|i| render! {
div { "hello {i}" }
})
})
}
});
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
assert!(dom.render_immediate().edits.is_empty());
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
assert!(dom.render_immediate_to_vec().edits.is_empty());
}
#[test]
fn remove_many() {
let mut dom = VirtualDom::new(|cx| {
let num = match cx.generation() % 3 {
let num = match generation() % 3 {
0 => 0,
1 => 1,
2 => 5,
_ => unreachable!(),
};
cx.render(rsx! {
(0..num).map(|i| rsx! { div { "hello {i}" } })
})
render! {(0..num).map(|i| render! { div { "hello {i}" } })}
});
{
let edits = dom.rebuild().santize();
let edits = dom.rebuild_to_vec().santize();
assert!(edits.templates.is_empty());
assert_eq!(
edits.edits,
@@ -329,12 +327,12 @@ fn remove_many() {
{
dom.mark_dirty(ScopeId::ROOT);
let edits = dom.render_immediate().santize();
let edits = dom.render_immediate_to_vec().santize();
assert_eq!(
edits.edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
HydrateText { path: &[0,], value: "hello 0", id: ElementId(3,) },
HydrateText { path: &[0,], value: "hello 0".to_string(), id: ElementId(3,) },
ReplaceWith { id: ElementId(1,), m: 1 },
]
);
@@ -342,18 +340,18 @@ fn remove_many() {
{
dom.mark_dirty(ScopeId::ROOT);
let edits = dom.render_immediate().santize();
let edits = dom.render_immediate_to_vec().santize();
assert_eq!(
edits.edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
HydrateText { path: &[0,], value: "hello 1", id: ElementId(4,) },
HydrateText { path: &[0,], value: "hello 1".to_string(), id: ElementId(4,) },
LoadTemplate { name: "template", index: 0, id: ElementId(5,) },
HydrateText { path: &[0,], value: "hello 2", id: ElementId(6,) },
HydrateText { path: &[0,], value: "hello 2".to_string(), id: ElementId(6,) },
LoadTemplate { name: "template", index: 0, id: ElementId(7,) },
HydrateText { path: &[0,], value: "hello 3", id: ElementId(8,) },
HydrateText { path: &[0,], value: "hello 3".to_string(), id: ElementId(8,) },
LoadTemplate { name: "template", index: 0, id: ElementId(9,) },
HydrateText { path: &[0,], value: "hello 4", id: ElementId(10,) },
HydrateText { path: &[0,], value: "hello 4".to_string(), id: ElementId(10,) },
InsertAfter { id: ElementId(2,), m: 4 },
]
);
@@ -361,7 +359,7 @@ fn remove_many() {
{
dom.mark_dirty(ScopeId::ROOT);
let edits = dom.render_immediate().santize();
let edits = dom.render_immediate_to_vec().santize();
assert_eq!(
edits.edits,
[
@@ -377,12 +375,12 @@ fn remove_many() {
{
dom.mark_dirty(ScopeId::ROOT);
let edits = dom.render_immediate().santize();
let edits = dom.render_immediate_to_vec().santize();
assert_eq!(
edits.edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(2,) },
HydrateText { path: &[0,], value: "hello 0", id: ElementId(3,) },
HydrateText { path: &[0,], value: "hello 0".to_string(), id: ElementId(3,) },
ReplaceWith { id: ElementId(11,), m: 1 },
]
)
+4 -6
View File
@@ -5,18 +5,18 @@ use dioxus::prelude::*;
#[test]
fn catches_panic() {
let mut dom = VirtualDom::new(app);
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
}
fn app(cx: Scope) -> Element {
cx.render(rsx! {
render! {
div {
h1 { "Title" }
NoneChild {}
ThrowChild {}
}
})
}
}
fn NoneChild(_cx: Scope) -> Element {
@@ -28,7 +28,5 @@ fn ThrowChild(cx: Scope) -> Element {
let _g: i32 = "123123".parse().throw()?;
cx.render(rsx! {
div {}
})
render! { div {} }
}
+3 -3
View File
@@ -9,7 +9,7 @@ fn events_propagate() {
set_event_converter(Box::new(dioxus_html::SerializedHtmlEventConverter));
let mut dom = VirtualDom::new(app);
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
// Top-level click is registered
dom.handle_event(
@@ -23,7 +23,7 @@ fn events_propagate() {
// break reference....
for _ in 0..5 {
dom.mark_dirty(ScopeId(0));
_ = dom.render_immediate();
_ = dom.render_immediate_to_vec();
}
// Lower click is registered
@@ -38,7 +38,7 @@ fn events_propagate() {
// break reference....
for _ in 0..5 {
dom.mark_dirty(ScopeId(0));
_ = dom.render_immediate();
_ = dom.render_immediate_to_vec();
}
// Stop propagation occurs
+3 -3
View File
@@ -311,7 +311,7 @@ fn create() {
for _ in 0..repeat_count {
let mut vdom =
VirtualDom::new_with_props(create_random_element, DepthProps { depth: 0, root: true });
let _ = vdom.rebuild();
let _ = vdom.rebuild_to_vec();
}
}
@@ -323,7 +323,7 @@ fn diff() {
for _ in 0..repeat_count {
let mut vdom =
VirtualDom::new_with_props(create_random_element, DepthProps { depth: 0, root: true });
let _ = vdom.rebuild();
let _ = vdom.rebuild_to_vec();
// A list of all elements that have had event listeners
// This is intentionally never cleared, so that we can test that calling event listeners that are removed doesn't cause a panic
let mut event_listeners = HashSet::new();
@@ -338,7 +338,7 @@ fn diff() {
);
}
{
let muts = vdom.render_immediate();
let muts = vdom.render_immediate_to_vec();
for mut_ in muts.edits {
if let Mutation::NewEventListener { name, id } = mut_ {
println!("new event listener on {:?} for {:?}", id, name);
+15 -13
View File
@@ -6,32 +6,34 @@ fn basic_syntax_is_a_template(cx: Scope) -> Element {
let asd = 123;
let var = 123;
cx.render(rsx! {
div { key: "12345",
class: "asd",
class: "{asd}",
class: if true { "{asd}" },
class: if false { "{asd}" },
onclick: move |_| {},
render! {
div { key: "12345", class: "asd", class: "{asd}", class: if true {
"{asd}"
}, class: if false {
"{asd}"
}, onclick: move |_| {},
div { "{var}" }
div {
h1 { "var" }
p { "you're great!" }
div { background_color: "red",
h1 { "var" }
div { b { "asd" } "not great" }
div {
b { "asd" }
"not great"
}
}
p { "you're great!" }
}
}
})
}
}
#[test]
fn dual_stream() {
let mut dom = VirtualDom::new(basic_syntax_is_a_template);
let bump = Bump::new();
let edits = dom.rebuild().santize();
let edits = dom.rebuild_to_vec().santize();
use Mutation::*;
assert_eq!(edits.edits, {
@@ -39,12 +41,12 @@ fn dual_stream() {
LoadTemplate { name: "template", index: 0, id: ElementId(1) },
SetAttribute {
name: "class",
value: (&*bump.alloc("asd 123 123".into_value(&bump))).into(),
value: "asd 123 123".into_value(),
id: ElementId(1),
ns: None,
},
NewEventListener { name: "click", id: ElementId(1) },
HydrateText { path: &[0, 0], value: "123", id: ElementId(2) },
NewEventListener { name: "click".to_string(), id: ElementId(1) },
HydrateText { path: &[0, 0], value: "123".to_string(), id: ElementId(2) },
AppendChildren { id: ElementId(0), m: 1 },
]
});
+12 -12
View File
@@ -18,21 +18,21 @@ fn manual_diffing() {
fn app(cx: Scope<AppProps>) -> Element {
let val = cx.props.value.lock().unwrap();
cx.render(rsx! { div { "{val}" } })
render! { div { "{val}" } }
};
let value = Arc::new(Mutex::new("Hello"));
let mut dom = VirtualDom::new_with_props(app, AppProps { value: value.clone() });
let _ = dom.rebuild(&mut dioxus_core::NoOpMutations);
let _ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
*value.lock().unwrap() = "goodbye";
assert_eq!(
dom.rebuild().santize().edits,
dom.rebuild_to_vec().santize().edits,
[
LoadTemplate { name: "template", index: 0, id: ElementId(3) },
HydrateText { path: &[0], value: "goodbye", id: ElementId(4) },
HydrateText { path: &[0], value: "goodbye".to_string(), id: ElementId(4) },
AppendChildren { m: 1, id: ElementId(0) }
]
);
@@ -45,18 +45,18 @@ fn events_generate() {
let count = cx.use_hook(|| 0);
match *count {
0 => cx.render(rsx! {
0 => render! {
div { onclick: move |_| *count += 1,
div { "nested" }
"Click me!"
}
}),
_ => cx.render(rsx!(())),
},
_ => render!(()),
}
};
let mut dom = VirtualDom::new(app);
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.handle_event(
"click",
@@ -66,7 +66,7 @@ fn events_generate() {
);
dom.mark_dirty(ScopeId::ROOT);
let edits = dom.render_immediate();
let edits = dom.render_immediate_to_vec();
assert_eq!(
edits.edits,
@@ -83,7 +83,7 @@ fn events_generate() {
// let render_phase = cx.use_hook(|| 0);
// *render_phase += 1;
// cx.render(match *render_phase {
// match *render_phase {
// 1 => rsx_without_templates!("Text0"),
// 2 => rsx_without_templates!(div {}),
// 3 => rsx_without_templates!("Text2"),
@@ -98,13 +98,13 @@ fn events_generate() {
// fn Child(cx: Scope) -> Element {
// println!("Running child");
// cx.render(rsx_without_templates! {
// render_without_templates! {
// h1 {}
// })
// }
// let mut dom = VirtualDom::new(app);
// let edits = dom.rebuild();
// let edits = dom.rebuild_to_vec();
// assert_eq!(
// edits.edits,
// [
+6 -11
View File
@@ -9,7 +9,7 @@ fn miri_rollover() {
set_event_converter(Box::new(SerializedHtmlEventConverter));
let mut dom = VirtualDom::new(App);
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
for _ in 0..3 {
dom.handle_event(
@@ -19,7 +19,7 @@ fn miri_rollover() {
true,
);
dom.process_events();
_ = dom.render_immediate();
_ = dom.render_immediate_to_vec();
}
}
@@ -28,7 +28,7 @@ fn App(cx: Scope) -> Element {
let mut idx = use_state(cx, || 0);
let onhover = |_| println!("go!");
cx.render(rsx! {
render! {
div {
button {
onclick: move |_| {
@@ -39,20 +39,15 @@ fn App(cx: Scope) -> Element {
}
button { onclick: move |_| idx -= 1, "-" }
ul {
(0..**idx).map(|i| rsx! {
(0..**idx).map(|i| render! {
ChildExample { i: i, onhover: onhover }
})
}
}
})
}
}
#[component]
fn ChildExample<'a>(cx: Scope<'a>, i: i32, onhover: EventHandler<'a, MouseEvent>) -> Element {
cx.render(rsx! {
li {
onmouseover: move |e| onhover.call(e),
"{i}"
}
})
render! { li { onmouseover: move |e| onhover.call(e), "{i}" } }
}
+27 -37
View File
@@ -4,16 +4,14 @@ use dioxus::prelude::*;
fn app_drops() {
#[component]
fn App(cx: Scope) -> Element {
cx.render(rsx! {
div {}
})
render! { div {} }
}
let mut dom = VirtualDom::new(App);
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.mark_dirty(ScopeId::ROOT);
_ = dom.render_immediate();
_ = dom.render_immediate_to_vec();
}
#[test]
@@ -25,16 +23,14 @@ fn hooks_drop() {
cx.use_hook(|| String::from("asd"));
cx.use_hook(|| String::from("asd"));
cx.render(rsx! {
div {}
})
render! { div {} }
}
let mut dom = VirtualDom::new(App);
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.mark_dirty(ScopeId::ROOT);
_ = dom.render_immediate();
_ = dom.render_immediate_to_vec();
}
#[test]
@@ -43,27 +39,23 @@ fn contexts_drop() {
fn App(cx: Scope) -> Element {
cx.provide_context(String::from("asd"));
cx.render(rsx! {
div {
ChildComp {}
}
})
render! {
div { ChildComp {} }
}
}
#[component]
fn ChildComp(cx: Scope) -> Element {
let el = cx.consume_context::<String>().unwrap();
cx.render(rsx! {
div { "hello {el}" }
})
render! { div { "hello {el}" } }
}
let mut dom = VirtualDom::new(App);
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.mark_dirty(ScopeId::ROOT);
_ = dom.render_immediate();
_ = dom.render_immediate_to_vec();
}
#[test]
@@ -74,16 +66,14 @@ fn tasks_drop() {
// tokio::time::sleep(std::time::Duration::from_millis(100000)).await;
});
cx.render(rsx! {
div { }
})
render! { div {} }
}
let mut dom = VirtualDom::new(App);
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.mark_dirty(ScopeId::ROOT);
_ = dom.render_immediate();
_ = dom.render_immediate_to_vec();
}
#[test]
@@ -91,43 +81,43 @@ fn root_props_drop() {
struct RootProps(String);
let mut dom = VirtualDom::new_with_props(
|cx| cx.render(rsx!( div { "{cx.props.0}" } )),
|cx| render!( div { "{cx.props.0}" } ),
RootProps("asdasd".to_string()),
);
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.mark_dirty(ScopeId::ROOT);
_ = dom.render_immediate();
_ = dom.render_immediate_to_vec();
}
#[test]
fn diffing_drops_old() {
#[component]
fn App(cx: Scope) -> Element {
cx.render(rsx! {
render! {
div {
match cx.generation() % 2 {
0 => rsx!( ChildComp1 { name: "asdasd".to_string() }),
1 => rsx!( ChildComp2 { name: "asdasd".to_string() }),
match generation() % 2 {
0 => render!( ChildComp1 { name: "asdasd".to_string() }),
1 => render!( ChildComp2 { name: "asdasd".to_string() }),
_ => todo!()
}
}
})
}
}
#[component]
fn ChildComp1(cx: Scope, name: String) -> Element {
cx.render(rsx! { "Hello {name}" })
render! {"Hello {name}"}
}
#[component]
fn ChildComp2(cx: Scope, name: String) -> Element {
cx.render(rsx! { "Goodbye {name}" })
render! {"Goodbye {name}"}
}
let mut dom = VirtualDom::new(App);
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.mark_dirty(ScopeId::ROOT);
_ = dom.render_immediate();
_ = dom.render_immediate_to_vec();
}
+26 -46
View File
@@ -10,19 +10,19 @@ use dioxus::prelude::*;
#[test]
fn test_memory_leak() {
fn app(cx: Scope) -> Element {
let val = cx.generation();
let val = generation();
cx.spawn(async {});
if val == 2 || val == 4 {
return cx.render(rsx!(()));
return render!(());
}
let name = cx.use_hook(|| String::from("numbers: "));
name.push_str("123 ");
cx.render(rsx!(
render!(
div { "Hello, world!" }
Child {}
Child {}
@@ -35,7 +35,7 @@ fn test_memory_leak() {
BorrowedChild { name: name }
BorrowedChild { name: name }
BorrowedChild { name: name }
))
)
}
#[derive(Props)]
@@ -44,44 +44,44 @@ fn test_memory_leak() {
}
fn BorrowedChild<'a>(cx: Scope<'a, BorrowedProps<'a>>) -> Element {
cx.render(rsx! {
render! {
div {
"goodbye {cx.props.name}"
Child {}
Child {}
}
})
}
}
fn Child(cx: Scope) -> Element {
render!(div { "goodbye world" })
render!( div { "goodbye world" } )
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
for _ in 0..5 {
dom.mark_dirty(ScopeId::ROOT);
_ = dom.render_immediate();
_ = dom.render_immediate_to_vec();
}
}
#[test]
fn memo_works_properly() {
fn app(cx: Scope) -> Element {
let val = cx.generation();
let val = generation();
if val == 2 || val == 4 {
return cx.render(rsx!(()));
return render!(());
}
let name = cx.use_hook(|| String::from("asd"));
cx.render(rsx!(
render!(
div { "Hello, world! {name}" }
Child { na: "asdfg".to_string() }
))
)
}
#[derive(PartialEq, Props)]
@@ -90,12 +90,12 @@ fn memo_works_properly() {
}
fn Child(cx: Scope<ChildProps>) -> Element {
render!(div { "goodbye world" })
render!( div { "goodbye world" } )
}
let mut dom = VirtualDom::new(app);
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
// todo!()
// dom.hard_diff(ScopeId::ROOT);
// dom.hard_diff(ScopeId::ROOT);
@@ -122,12 +122,12 @@ fn free_works_on_root_hooks() {
}
fn child_component(cx: Scope<AppProps>) -> Element {
render!(div { "{cx.props.inner}" })
render!( div { "{cx.props.inner}" } )
}
let ptr = Rc::new("asdasd".to_string());
let mut dom = VirtualDom::new_with_props(app, AppProps { inner: ptr.clone() });
let _ = dom.rebuild(&mut dioxus_core::NoOpMutations);
let _ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
// ptr gets cloned into props and then into the hook
assert_eq!(Rc::strong_count(&ptr), 4);
@@ -166,35 +166,15 @@ fn supports_async() {
let mid = colors[1];
let small = colors[2];
cx.render(rsx! {
div {
background: "{big}",
height: "stretch",
width: "stretch",
padding: "50",
label {
"hello",
render! {
div { background: "{big}", height: "stretch", width: "stretch", padding: "50",
label { "hello" }
div { background: "{mid}", height: "auto", width: "stretch", padding: "{padding}",
label { "World" }
div { background: "{small}", height: "auto", width: "stretch", padding: "20", label { "ddddddd" } }
}
div {
background: "{mid}",
height: "auto",
width: "stretch",
padding: "{padding}",
label {
"World",
}
div {
background: "{small}",
height: "auto",
width: "stretch",
padding: "20",
label {
"ddddddd",
}
}
},
}
})
}
}
let rt = tokio::runtime::Builder::new_current_thread()
@@ -204,11 +184,11 @@ fn supports_async() {
rt.block_on(async {
let mut dom = VirtualDom::new(app);
let _ = dom.rebuild(&mut dioxus_core::NoOpMutations);
let _ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
for _ in 0..10 {
dom.wait_for_work().await;
let _edits = dom.render_immediate();
let _edits = dom.render_immediate_to_vec();
}
});
}
+1 -1
View File
@@ -2,7 +2,7 @@
use dioxus::prelude::*;
/// Ensure no issues with not calling rebuild
/// Ensure no issues with not calling rebuild_to_vec
#[test]
fn root_node_isnt_null() {
let dom = VirtualDom::new(|cx| render!("Hello world!"));
+3 -3
View File
@@ -9,7 +9,7 @@ fn it_works() {
.unwrap()
.block_on(async {
let mut dom = VirtualDom::new(app);
_ = dom.rebuild(&mut dioxus_core::NoOpMutations);
_ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
dom.wait_for_suspense().await;
let out = dioxus_ssr::render(&dom);
@@ -20,12 +20,12 @@ fn it_works() {
}
fn app(cx: Scope) -> Element {
cx.render(rsx!(
render!(
div {
"Waiting for... "
suspended_child {}
}
))
)
}
fn suspended_child(cx: Scope) -> Element {
+2 -2
View File
@@ -25,12 +25,12 @@ async fn it_works() {
});
});
cx.render(rsx!(()))
render!(())
}
let mut dom = VirtualDom::new(app);
let _ = dom.rebuild(&mut dioxus_core::NoOpMutations);
let _ = dom.rebuild_to_vec(&mut dioxus_core::NoOpMutations);
tokio::select! {
_ = dom.wait_for_work() => {}
@@ -300,7 +300,7 @@ fn persist_removes() {
use dioxus::prelude::*;
#[allow(non_snake_case)]
fn Base(cx: Scope) -> Element {
let children = match cx.generation() % 2 {
let children = match generation() % 2 {
0 => 3,
1 => 2,
_ => unreachable!(),
@@ -381,7 +381,7 @@ fn persist_instertions_before() {
use dioxus::prelude::*;
#[allow(non_snake_case)]
fn Base(cx: Scope) -> Element {
let children = match cx.generation() % 2 {
let children = match generation() % 2 {
0 => 3,
1 => 2,
_ => unreachable!(),
@@ -439,7 +439,7 @@ fn persist_instertions_after() {
use dioxus::prelude::*;
#[allow(non_snake_case)]
fn Base(cx: Scope) -> Element {
let children = match cx.generation() % 2 {
let children = match generation() % 2 {
0 => 3,
1 => 2,
_ => unreachable!(),
+1 -1
View File
@@ -56,7 +56,7 @@ fn deref_signal() {
#[test]
fn drop_signals() {
let mut dom = VirtualDom::new(|cx| {
let generation = cx.generation();
let generation = generation();
let count = if generation % 2 == 0 { 10 } else { 0 };
render! {
+3 -3
View File
@@ -65,10 +65,10 @@ fn memos_prevents_component_rerun() {
|cx| {
let mut signal = use_signal(cx, || 0);
if cx.generation() == 1 {
if generation() == 1 {
*signal.write() = 0;
}
if cx.generation() == 2 {
if generation() == 2 {
println!("Writing to signal");
*signal.write() = 1;
}
@@ -108,7 +108,7 @@ fn memos_prevents_component_rerun() {
signal.value()
})
});
match cx.generation() {
match generation() {
0 => {
assert_eq!(memo.value(), 0);
}
+1 -1
View File
@@ -22,7 +22,7 @@ fn reading_subscribes() {
let mut signal = use_signal(cx, || 0);
println!("Parent: {:?}", cx.scope_id());
if cx.generation() == 1 {
if generation() == 1 {
signal += 1;
}