Merge branch 'master' into pr/atty303/1349

This commit is contained in:
Evan Almloff committed 2024-01-06 08:52:37 -06:00
commit e5df83ceec
278 files changed
+11299 -3674

No files matched your search

+2 -2
View File
@@ -24,9 +24,9 @@ fn NoneChild(_cx: Scope) -> Element {
}
fn ThrowChild(cx: Scope) -> Element {
cx.throw(std::io::Error::new(std::io::ErrorKind::AddrInUse, "asd"))?;
Err(std::io::Error::new(std::io::ErrorKind::AddrInUse, "asd")).throw()?;
let _g: i32 = "123123".parse().throw(cx)?;
let _g: i32 = "123123".parse().throw()?;
cx.render(rsx! {
div {}
+67
View File
@@ -0,0 +1,67 @@
use dioxus::prelude::*;
use dioxus_core::ElementId;
use std::{rc::Rc, sync::Mutex};
static CLICKS: Mutex<usize> = Mutex::new(0);
#[test]
fn events_propagate() {
set_event_converter(Box::new(dioxus_html::SerializedHtmlEventConverter));
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
// Top-level click is registered
dom.handle_event("click", Rc::new(PlatformEventData::new(Box::<SerializedMouseData>::default())), ElementId(1), true);
assert_eq!(*CLICKS.lock().unwrap(), 1);
// break reference....
for _ in 0..5 {
dom.mark_dirty(ScopeId(0));
_ = dom.render_immediate();
}
// Lower click is registered
dom.handle_event("click", Rc::new(PlatformEventData::new(Box::<SerializedMouseData>::default())), ElementId(2), true);
assert_eq!(*CLICKS.lock().unwrap(), 3);
// break reference....
for _ in 0..5 {
dom.mark_dirty(ScopeId(0));
_ = dom.render_immediate();
}
// Stop propagation occurs
dom.handle_event("click", Rc::new(PlatformEventData::new(Box::<SerializedMouseData>::default())), ElementId(2), true);
assert_eq!(*CLICKS.lock().unwrap(), 3);
}
fn app(cx: Scope) -> Element {
render! {
div { onclick: move |_| {
println!("top clicked");
*CLICKS.lock().unwrap() += 1;
},
vec![
render! {
problematic_child {}
}
].into_iter()
}
}
}
fn problematic_child(cx: Scope) -> Element {
render! {
button { onclick: move |evt| {
println!("bottom clicked");
let mut clicks = CLICKS.lock().unwrap();
if *clicks == 3 {
evt.stop_propagation();
} else {
*clicks += 1;
}
} }
}
}
+29 -30
View File
@@ -2,7 +2,7 @@
use dioxus::prelude::Props;
use dioxus_core::{MountedAttribute, *};
use std::{cell::Cell, collections::HashSet};
use std::{cell::Cell, cfg, collections::HashSet};
fn random_ns() -> Option<&'static str> {
let namespace = rand::random::<u8>() % 2;
@@ -170,22 +170,23 @@ fn create_random_dynamic_node(cx: &ScopeState, depth: usize) -> DynamicNode {
let range = if depth > 5 { 1 } else { 4 };
match rand::random::<u8>() % range {
0 => DynamicNode::Placeholder(Default::default()),
1 => cx.make_node((0..(rand::random::<u8>() % 5)).map(|_| VNode {
key: None,
parent: Default::default(),
template: Cell::new(Template {
name: concat!(file!(), ":", line!(), ":", column!(), ":0"),
roots: &[TemplateNode::Dynamic { id: 0 }],
node_paths: &[&[0]],
attr_paths: &[],
}),
root_ids: bumpalo::collections::Vec::new_in(cx.bump()).into(),
dynamic_nodes: cx.bump().alloc([cx.component(
create_random_element,
DepthProps { depth, root: false },
"create_random_element",
)]),
dynamic_attrs: &[],
1 => cx.make_node((0..(rand::random::<u8>() % 5)).map(|_| {
VNode::new(
None,
Template {
name: concat!(file!(), ":", line!(), ":", column!(), ":0"),
roots: &[TemplateNode::Dynamic { id: 0 }],
node_paths: &[&[0]],
attr_paths: &[],
},
bumpalo::collections::Vec::new_in(cx.bump()),
cx.bump().alloc([cx.component(
create_random_element,
DepthProps { depth, root: false },
"create_random_element",
)]),
&[],
)
})),
2 => cx.component(
create_random_element,
@@ -272,13 +273,11 @@ fn create_random_element(cx: Scope<DepthProps>) -> Element {
)
.into_boxed_str(),
));
// println!("{template:#?}");
let node = VNode {
key: None,
parent: None,
template: Cell::new(template),
root_ids: bumpalo::collections::Vec::new_in(cx.bump()).into(),
dynamic_nodes: {
let node = VNode::new(
None,
template,
bumpalo::collections::Vec::new_in(cx.bump()),
{
let dynamic_nodes: Vec<_> = dynamic_node_types
.iter()
.map(|ty| match ty {
@@ -292,12 +291,12 @@ fn create_random_element(cx: Scope<DepthProps>) -> Element {
.collect();
cx.bump().alloc(dynamic_nodes)
},
dynamic_attrs: cx.bump().alloc(
cx.bump().alloc(
(0..template.attr_paths.len())
.map(|_| create_random_dynamic_attr(cx))
.collect::<Vec<_>>(),
),
};
);
Some(node)
}
_ => None,
@@ -307,10 +306,10 @@ fn create_random_element(cx: Scope<DepthProps>) -> Element {
}
// test for panics when creating random nodes and templates
#[cfg(not(miri))]
#[test]
fn create() {
for _ in 0..1000 {
let repeat_count = if cfg!(miri) { 100 } else { 1000 };
for _ in 0..repeat_count {
let mut vdom =
VirtualDom::new_with_props(create_random_element, DepthProps { depth: 0, root: true });
let _ = vdom.rebuild();
@@ -319,10 +318,10 @@ fn create() {
// test for panics when diffing random nodes
// This test will change the template every render which is not very realistic, but it helps stress the system
#[cfg(not(miri))]
#[test]
fn diff() {
for _ in 0..100000 {
let repeat_count = if cfg!(miri) { 100 } else { 1000 };
for _ in 0..repeat_count {
let mut vdom =
VirtualDom::new_with_props(create_random_element, DepthProps { depth: 0, root: true });
let _ = vdom.rebuild();
+8 -1
View File
@@ -4,6 +4,7 @@
//! Tests for the lifecycle of components.
use dioxus::core::{ElementId, Mutation::*};
use dioxus::prelude::*;
use dioxus_html::SerializedHtmlEventConverter;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
@@ -39,6 +40,7 @@ fn manual_diffing() {
#[test]
fn events_generate() {
set_event_converter(Box::new(SerializedHtmlEventConverter));
fn app(cx: Scope) -> Element {
let count = cx.use_hook(|| 0);
@@ -56,7 +58,12 @@ fn events_generate() {
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
dom.handle_event("click", Rc::new(MouseData::default()), ElementId(1), true);
dom.handle_event(
"click",
Rc::new(PlatformEventData::new(Box::<SerializedMouseData>::default())),
ElementId(1),
true,
);
dom.mark_dirty(ScopeId::ROOT);
let edits = dom.render_immediate();
+9 -1
View File
@@ -1,15 +1,23 @@
use crate::dioxus_elements::SerializedMouseData;
use dioxus::prelude::*;
use dioxus_core::ElementId;
use dioxus_elements::SerializedHtmlEventConverter;
use std::rc::Rc;
#[test]
fn miri_rollover() {
set_event_converter(Box::new(SerializedHtmlEventConverter));
let mut dom = VirtualDom::new(App);
_ = dom.rebuild();
for _ in 0..3 {
dom.handle_event("click", Rc::new(MouseData::default()), ElementId(2), true);
dom.handle_event(
"click",
Rc::new(PlatformEventData::new(Box::<SerializedMouseData>::default())),
ElementId(2),
true,
);
dom.process_events();
_ = dom.render_immediate();
}
+1 -1
View File
@@ -11,7 +11,7 @@ fn it_works() {
let mut dom = VirtualDom::new(app);
_ = dom.rebuild();
dom.wait_for_suspense().await;
let out = dioxus_ssr::pre_render(&dom);
let out = dioxus_ssr::render(&dom);
assert_eq!(out, "<div>Waiting for... child</div>");
+25 -25
View File
@@ -1,13 +1,33 @@
//! Verify that tasks get polled by the virtualdom properly, and that we escape wait_for_work safely
use dioxus::prelude::*;
use std::{sync::atomic::AtomicUsize, time::Duration};
static POLL_COUNT: AtomicUsize = AtomicUsize::new(0);
#[cfg(not(miri))]
#[tokio::test]
async fn it_works() {
use dioxus::prelude::*;
use std::{sync::atomic::AtomicUsize, time::Duration};
static POLL_COUNT: AtomicUsize = AtomicUsize::new(0);
fn app(cx: Scope) -> Element {
cx.use_hook(|| {
cx.spawn(async {
for x in 0..10 {
tokio::time::sleep(Duration::from_micros(50)).await;
POLL_COUNT.fetch_add(x, std::sync::atomic::Ordering::Relaxed);
}
});
cx.spawn(async {
for x in 0..10 {
tokio::time::sleep(Duration::from_micros(25)).await;
POLL_COUNT.fetch_add(x * 2, std::sync::atomic::Ordering::Relaxed);
}
});
});
cx.render(rsx!(()))
}
let mut dom = VirtualDom::new(app);
let _ = dom.rebuild();
@@ -24,23 +44,3 @@ async fn it_works() {
135
);
}
fn app(cx: Scope) -> Element {
cx.use_hook(|| {
cx.spawn(async {
for x in 0..10 {
tokio::time::sleep(Duration::from_micros(50)).await;
POLL_COUNT.fetch_add(x, std::sync::atomic::Ordering::Relaxed);
}
});
cx.spawn(async {
for x in 0..10 {
tokio::time::sleep(Duration::from_micros(25)).await;
POLL_COUNT.fetch_add(x * 2, std::sync::atomic::Ordering::Relaxed);
}
});
});
cx.render(rsx!(()))
}