diff --git a/packages/core/compile_tests/props_safety.rs b/packages/core/compile_tests/props_safety.rs index 1a0411be9..00a110a43 100644 --- a/packages/core/compile_tests/props_safety.rs +++ b/packages/core/compile_tests/props_safety.rs @@ -17,8 +17,8 @@ struct Testing<'a> { borrowed: &'a RefCell>, } -fn unsafe_child_component<'a>(cx: Scope<'a, Testing<'a>>) -> Element { - let Testing { borrowed } = cx.props; +fn unsafe_child_component<'a>(cx: Testing) -> Element { + let Testing { borrowed } = cx; let borrowed_temporary_data = cx.use_hook(|| String::from("This data is only valid for the lifetime of the child")); diff --git a/packages/core/compile_tests/props_safety_temporary_values.rs b/packages/core/compile_tests/props_safety_temporary_values.rs index 81c8ff108..e7f8b7a87 100644 --- a/packages/core/compile_tests/props_safety_temporary_values.rs +++ b/packages/core/compile_tests/props_safety_temporary_values.rs @@ -17,8 +17,8 @@ struct Testing<'a> { borrowed: &'a Vec, } -fn unsafe_child_component<'a>(cx: Scope<'a, Testing<'a>>) -> Element { +fn unsafe_child_component<'a>(cx: Testing) -> Element { cx.render(rsx! { - div { "{cx.props.borrowed:?}" } + div { "{cx.borrowed:?}" } }) } diff --git a/packages/core/src/error_boundary.rs b/packages/core/src/error_boundary.rs index 6c3349540..7ea426048 100644 --- a/packages/core/src/error_boundary.rs +++ b/packages/core/src/error_boundary.rs @@ -139,7 +139,7 @@ impl ErrorBoundary { /// /// ```rust, ignore /// #[component] -/// fn App(cx: Scope, count: String) -> Element { +/// fn App( count: String) -> Element { /// let id: i32 = count.parse().throw()?; /// /// cx.render(rsx! { @@ -164,7 +164,7 @@ pub trait Throw: Sized { /// /// ```rust, ignore /// #[component] - /// fn App(cx: Scope, count: String) -> Element { + /// fn App( count: String) -> Element { /// let id: i32 = count.parse().throw()?; /// /// cx.render(rsx! { @@ -187,7 +187,7 @@ pub trait Throw: Sized { /// /// ```rust, ignore /// #[component] - /// fn App(cx: Scope, count: String) -> Element { + /// fn App( count: String) -> Element { /// let id: i32 = count.parse().throw()?; /// /// cx.render(rsx! { diff --git a/packages/core/src/events.rs b/packages/core/src/events.rs index b2e87262d..e04c4df6f 100644 --- a/packages/core/src/events.rs +++ b/packages/core/src/events.rs @@ -145,10 +145,10 @@ impl std::fmt::Debug for Event { /// onclick: EventHandler<'a, MouseEvent>, /// } /// -/// fn MyComponent(cx: Scope<'a, MyProps<'a>>) -> Element { +/// fn MyComponent(cx: MyProps) -> Element { /// cx.render(rsx!{ /// button { -/// onclick: move |evt| cx.props.onclick.call(evt), +/// onclick: move |evt| cx.onclick.call(evt), /// } /// }) /// } diff --git a/packages/core/src/fragment.rs b/packages/core/src/fragment.rs index 6c367ec46..9fc1d3c62 100644 --- a/packages/core/src/fragment.rs +++ b/packages/core/src/fragment.rs @@ -80,7 +80,7 @@ impl FragmentBuilder { /// cx.render(rsx!{ /// div { /// h1 {"Title card"} -/// {cx.props.children} +/// {cx.children} /// } /// }) /// } diff --git a/packages/core/src/properties.rs b/packages/core/src/properties.rs index c7800e900..a7ec3e741 100644 --- a/packages/core/src/properties.rs +++ b/packages/core/src/properties.rs @@ -67,8 +67,39 @@ impl EmptyBuilder { /// This utility function launches the builder method so rsx! and html! macros can use the typed-builder pattern /// to initialize a component's props. -pub fn fc_to_builder(_: fn(T) -> Element) -> T::Builder { - T::builder() +pub fn fc_to_builder, P>( + _: F, +) -> <>::Props as Properties>::Builder { + F::Props::builder() +} + +/// A function pointer that can be used to create a component. +pub trait HasProps

{ + type Props: Properties; +} + +impl Element> HasProps<(T,)> for F { + type Props = T; +} + +#[doc(hidden)] +pub struct ZeroElementMarker; +impl Element> HasProps for F { + type Props = (); +} + +#[test] +fn test_empty_builder() { + fn app() -> Element { + render!(div {}) + } + fn app2(_: ()) -> Element { + render!(div {}) + } + let builder = fc_to_builder(app); + builder.build(); + let builder = fc_to_builder(app2); + builder.build(); } #[cfg(not(miri))] diff --git a/packages/core/src/runtime.rs b/packages/core/src/runtime.rs index 09b0c96e9..6450675af 100644 --- a/packages/core/src/runtime.rs +++ b/packages/core/src/runtime.rs @@ -132,7 +132,7 @@ impl Runtime { /// } /// /// fn Component(cx: Scope) -> Element { -/// cx.use_hook(|| RuntimeGuard::new(cx.props.runtime.clone())); +/// cx.use_hook(|| RuntimeGuard::new(cx.runtime.clone())); /// /// render! { div {} } /// } diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index 01799d1cb..e6fbf4252 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -36,7 +36,7 @@ use std::{any::Any, cell::Cell, collections::BTreeSet, future::Future, rc::Rc}; /// /// fn App(cx: Scope) -> Element { /// cx.render(rsx!( -/// div {"hello, {cx.props.title}"} +/// div {"hello, {cx.title}"} /// )) /// } /// ``` @@ -58,25 +58,25 @@ use std::{any::Any, cell::Cell, collections::BTreeSet, future::Future, rc::Rc}; /// fn App(cx: Scope) -> Element { /// cx.render(rsx!( /// NavBar { routes: ROUTES } -/// Title { "{cx.props.title}" } +/// Title { "{cx.title}" } /// Footer {} /// )) /// } /// /// #[component] -/// fn NavBar(cx: Scope, routes: &'static str) -> Element { +/// fn NavBar( routes: &'static str) -> Element { /// cx.render(rsx! { /// div { "Routes: {routes}" } /// }) /// } /// /// #[component] -/// fn Footer(cx: Scope) -> Element { +/// fn Footer() -> Element { /// cx.render(rsx! { div { "Footer" } }) /// } /// /// #[component] -/// fn Title<'a>(cx: Scope<'a>, children: Element) -> Element { +/// fn Title<'a>( children: Element) -> Element { /// cx.render(rsx! { /// div { id: "title", children } /// }) @@ -218,7 +218,7 @@ impl VirtualDom { /// /// # Example /// ```rust, ignore - /// fn Example(cx: Scope) -> Element { + /// fn Example() -> Element { /// cx.render(rsx!( div { "hello world" } )) /// } /// @@ -248,7 +248,7 @@ impl VirtualDom { /// } /// /// fn Example(cx: Scope) -> Element { - /// cx.render(rsx!{ div{ "hello {cx.props.name}" } }) + /// cx.render(rsx!{ div{ "hello {cx.name}" } }) /// } /// /// let dom = VirtualDom::new(Example); diff --git a/packages/core/tests/attr_cleanup.rs b/packages/core/tests/attr_cleanup.rs index 4581b601a..6d3bd157a 100644 --- a/packages/core/tests/attr_cleanup.rs +++ b/packages/core/tests/attr_cleanup.rs @@ -23,7 +23,7 @@ fn attrs_cycle() { let bump = Bump::new(); assert_eq!( - dom.rebuild_to_vec_to_vec().santize().edits, + dom.rebuild_to_vec().santize().edits, [ LoadTemplate { name: "template", index: 0, id: ElementId(1,) }, AppendChildren { m: 1, id: ElementId(0) }, diff --git a/packages/core/tests/borrowedstate.rs b/packages/core/tests/borrowedstate.rs index 50bb8c858..4d533688b 100644 --- a/packages/core/tests/borrowedstate.rs +++ b/packages/core/tests/borrowedstate.rs @@ -21,7 +21,7 @@ fn test_borrowed_state() { ); } -fn Parent(cx: Scope) -> Element { +fn Parent() -> Element { let w1 = cx.use_hook(|| String::from("w1")); render! { @@ -34,11 +34,11 @@ struct ChildProps<'a> { name: &'a str, } -fn Child<'a>(cx: Scope<'a, ChildProps<'a>>) -> Element { +fn Child<'a>(cx: ChildProps) -> Element { render! { div { h1 { "it's nested" } - Child2 { name: cx.props.name } + Child2 { name: cx.name } } } } @@ -48,6 +48,6 @@ struct Grandchild<'a> { name: &'a str, } -fn Child2<'a>(cx: Scope<'a, Grandchild<'a>>) -> Element { - render!( div { "Hello {cx.props.name}!" } ) +fn Child2<'a>(cx: Grandchild) -> Element { + render!( div { "Hello {cx.name}!" } ) } diff --git a/packages/core/tests/context_api.rs b/packages/core/tests/context_api.rs index 61ec9e3b1..59e425bc4 100644 --- a/packages/core/tests/context_api.rs +++ b/packages/core/tests/context_api.rs @@ -9,11 +9,11 @@ fn state_shares() { render!(child_1 {}) } - fn child_1(cx: Scope) -> Element { + fn child_1() -> Element { render!(child_2 {}) } - fn child_2(cx: Scope) -> Element { + fn child_2() -> Element { let value = cx.consume_context::().unwrap(); render!("Value is {value}") } diff --git a/packages/core/tests/create_dom.rs b/packages/core/tests/create_dom.rs index dc5b4a5f0..112811e5a 100644 --- a/packages/core/tests/create_dom.rs +++ b/packages/core/tests/create_dom.rs @@ -134,10 +134,10 @@ fn create_components() { children: Element, } - fn Child<'a>(cx: Scope<'a, ChildProps<'a>>) -> Element { + fn Child<'a>(cx: ChildProps) -> Element { render! { h1 {} - div { &cx.props.children } + div { &cx.children } p {} } } diff --git a/packages/core/tests/create_fragments.rs b/packages/core/tests/create_fragments.rs index 22ccaac48..f9b4f0dd0 100644 --- a/packages/core/tests/create_fragments.rs +++ b/packages/core/tests/create_fragments.rs @@ -75,7 +75,7 @@ fn fragments_across_components() { } } - fn demo_child(cx: Scope) -> Element { + fn demo_child() -> Element { let world = "world"; render! { "hellO!", world } } diff --git a/packages/core/tests/create_passthru.rs b/packages/core/tests/create_passthru.rs index d8336a678..3628ac2af 100644 --- a/packages/core/tests/create_passthru.rs +++ b/packages/core/tests/create_passthru.rs @@ -5,7 +5,6 @@ use dioxus_core::ElementId; /// Should push the text node onto the stack and modify it #[test] fn nested_passthru_creates() { - #[component] fn App() -> Element { render! { PassThru { @@ -17,7 +16,7 @@ fn nested_passthru_creates() { } #[component] - fn PassThru<'a>(cx: Scope<'a>, children: Element) -> Element { + fn PassThru<'a>(children: Element) -> Element { render!(children) } @@ -38,7 +37,6 @@ fn nested_passthru_creates() { /// Take note on how we don't spit out the template for child_comp since it's entirely dynamic #[test] fn nested_passthru_creates_add() { - #[component] fn App() -> Element { render! { ChildComp { @@ -55,7 +53,7 @@ fn nested_passthru_creates_add() { } #[component] - fn ChildComp<'a>(cx: Scope, children: Element) -> Element { + fn ChildComp<'a>(children: Element) -> Element { render! {children} } @@ -80,7 +78,6 @@ fn nested_passthru_creates_add() { /// note that the template is all dynamic roots - so it doesn't actually get cached as a template #[test] fn dynamic_node_as_root() { - #[component] fn App() -> Element { let a = 123; let b = 456; diff --git a/packages/core/tests/diff_component.rs b/packages/core/tests/diff_component.rs index a8f224c4f..ee1082adf 100644 --- a/packages/core/tests/diff_component.rs +++ b/packages/core/tests/diff_component.rs @@ -37,21 +37,21 @@ fn component_swap() { } } - fn nav_bar(cx: Scope) -> Element { + fn nav_bar() -> Element { render! { h1 { "NavBar", (0..3).map(|_| render!(nav_link {})) } } } - fn nav_link(cx: Scope) -> Element { + fn nav_link() -> Element { render!( h1 { "nav_link" } ) } - fn dash_board(cx: Scope) -> Element { + fn dash_board() -> Element { render!( div { "dashboard" } ) } - fn dash_results(cx: Scope) -> Element { + fn dash_results() -> Element { render!( div { "results" } ) } diff --git a/packages/core/tests/error_boundary.rs b/packages/core/tests/error_boundary.rs index 153fe723c..97b03ad8e 100644 --- a/packages/core/tests/error_boundary.rs +++ b/packages/core/tests/error_boundary.rs @@ -19,11 +19,11 @@ fn app() -> Element { } } -fn NoneChild(_cx: Scope) -> Element { +fn NoneChild(_) -> Element { None } -fn ThrowChild(cx: Scope) -> Element { +fn ThrowChild() -> Element { Err(std::io::Error::new(std::io::ErrorKind::AddrInUse, "asd")).throw()?; let _g: i32 = "123123".parse().throw()?; diff --git a/packages/core/tests/event_propagation.rs b/packages/core/tests/event_propagation.rs index 8f3b3a509..0792c9ae3 100644 --- a/packages/core/tests/event_propagation.rs +++ b/packages/core/tests/event_propagation.rs @@ -67,7 +67,7 @@ fn app() -> Element { } } -fn problematic_child(cx: Scope) -> Element { +fn problematic_child() -> Element { render! { button { onclick: move |evt| { println!("bottom clicked"); diff --git a/packages/core/tests/fuzzing.rs b/packages/core/tests/fuzzing.rs index 1fbac950b..5e5d1ca9b 100644 --- a/packages/core/tests/fuzzing.rs +++ b/packages/core/tests/fuzzing.rs @@ -238,10 +238,10 @@ struct BorrowedDepthProps<'a> { inner: DepthProps, } -fn create_random_element_borrowed<'a>(cx: Scope<'a, BorrowedDepthProps<'a>>) -> Element { - println!("{}", cx.props.borrow); +fn create_random_element_borrowed<'a>(cx: BorrowedDepthProps) -> Element { + println!("{}", cx.borrow); let bump = cx.bump(); - let allocated = bump.alloc(Scoped { scope: cx, props: &cx.props.inner }); + let allocated = bump.alloc(Scoped { scope: cx, props: &cx.inner }); create_random_element(allocated) } @@ -255,7 +255,7 @@ fn create_random_element(cx: Scope) -> Element { if rand::random::() % 10 == 0 { cx.needs_update(); } - let range = if cx.props.root { 2 } else { 3 }; + let range = if cx.root { 2 } else { 3 }; let node = match rand::random::() % range { 0 | 1 => { let (template, dynamic_node_types) = create_random_template(Box::leak( @@ -283,9 +283,7 @@ fn create_random_element(cx: Scope) -> Element { DynamicNodeType::Text => DynamicNode::Text(VText::new(Box::leak( format!("{}", rand::random::()).into_boxed_str(), ))), - DynamicNodeType::Other => { - create_random_dynamic_node(cx, cx.props.depth + 1) - } + DynamicNodeType::Other => create_random_dynamic_node(cx, cx.depth + 1), }) .collect(); cx.bump().alloc(dynamic_nodes) diff --git a/packages/core/tests/kitchen_sink.rs b/packages/core/tests/kitchen_sink.rs index 6342a8c2b..523d4611e 100644 --- a/packages/core/tests/kitchen_sink.rs +++ b/packages/core/tests/kitchen_sink.rs @@ -2,7 +2,7 @@ use bumpalo::Bump; use dioxus::core::{ElementId, Mutation}; use dioxus::prelude::*; -fn basic_syntax_is_a_template(cx: Scope) -> Element { +fn basic_syntax_is_a_template() -> Element { let asd = 123; let var = 123; diff --git a/packages/core/tests/lifecycle.rs b/packages/core/tests/lifecycle.rs index fe54eac44..78becc3b8 100644 --- a/packages/core/tests/lifecycle.rs +++ b/packages/core/tests/lifecycle.rs @@ -17,7 +17,7 @@ fn manual_diffing() { } fn app(cx: Scope) -> Element { - let val = cx.props.value.lock().unwrap(); + let val = cx.value.lock().unwrap(); render! { div { "{val}" } } }; @@ -96,7 +96,7 @@ fn events_generate() { // }) // }; -// fn Child(cx: Scope) -> Element { +// fn Child() -> Element { // println!("Running child"); // render_without_templates! { // h1 {} diff --git a/packages/core/tests/miri_full_app.rs b/packages/core/tests/miri_full_app.rs index 523b888cc..7167e6560 100644 --- a/packages/core/tests/miri_full_app.rs +++ b/packages/core/tests/miri_full_app.rs @@ -25,7 +25,7 @@ fn miri_rollover() { #[component] fn App() -> Element { - let mut idx = use_state(cx, || 0); + let mut idx = use_signal(|| 0); let onhover = |_| println!("go!"); render! { @@ -48,6 +48,6 @@ fn App() -> Element { } #[component] -fn ChildExample<'a>(cx: Scope<'a>, i: i32, onhover: EventHandler<'a, MouseEvent>) -> Element { +fn ChildExample<'a>(i: i32, onhover: EventHandler<'a, MouseEvent>) -> Element { render! { li { onmouseover: move |e| onhover.call(e), "{i}" } } } diff --git a/packages/core/tests/miri_simple.rs b/packages/core/tests/miri_simple.rs index a3d7d04a2..f5e26a3dc 100644 --- a/packages/core/tests/miri_simple.rs +++ b/packages/core/tests/miri_simple.rs @@ -2,7 +2,6 @@ use dioxus::prelude::*; #[test] fn app_drops() { - #[component] fn App() -> Element { render! { div {} } } @@ -16,7 +15,6 @@ fn app_drops() { #[test] fn hooks_drop() { - #[component] fn App() -> Element { cx.use_hook(|| String::from("asd")); cx.use_hook(|| String::from("asd")); @@ -35,7 +33,6 @@ fn hooks_drop() { #[test] fn contexts_drop() { - #[component] fn App() -> Element { cx.provide_context(String::from("asd")); @@ -45,7 +42,7 @@ fn contexts_drop() { } #[component] - fn ChildComp(cx: Scope) -> Element { + fn ChildComp() -> Element { let el = cx.consume_context::().unwrap(); render! { div { "hello {el}" } } @@ -60,7 +57,6 @@ fn contexts_drop() { #[test] fn tasks_drop() { - #[component] fn App() -> Element { cx.spawn(async { // tokio::time::sleep(std::time::Duration::from_millis(100000)).await; @@ -81,7 +77,7 @@ fn root_props_drop() { struct RootProps(String); let mut dom = VirtualDom::new_with_props( - |cx| render!( div { "{cx.props.0}" } ), + |cx| render!( div { "{cx.0}" } ), RootProps("asdasd".to_string()), ); @@ -92,7 +88,6 @@ fn root_props_drop() { #[test] fn diffing_drops_old() { - #[component] fn App() -> Element { render! { div { @@ -106,12 +101,12 @@ fn diffing_drops_old() { } #[component] - fn ChildComp1(cx: Scope, name: String) -> Element { + fn ChildComp1(name: String) -> Element { render! {"Hello {name}"} } #[component] - fn ChildComp2(cx: Scope, name: String) -> Element { + fn ChildComp2(name: String) -> Element { render! {"Goodbye {name}"} } diff --git a/packages/core/tests/miri_stress.rs b/packages/core/tests/miri_stress.rs index 6654f6d3a..fbfa5b295 100644 --- a/packages/core/tests/miri_stress.rs +++ b/packages/core/tests/miri_stress.rs @@ -38,22 +38,22 @@ fn test_memory_leak() { ) } - #[derive(Props)] - struct BorrowedProps<'a> { - name: &'a str, + #[derive(Props, Clone, PartialEq)] + struct BorrowedProps { + name: String, } - fn BorrowedChild<'a>(cx: Scope<'a, BorrowedProps<'a>>) -> Element { + fn BorrowedChild(cx: BorrowedProps) -> Element { render! { div { - "goodbye {cx.props.name}" + "goodbye {cx.name}" Child {} Child {} } } } - fn Child(cx: Scope) -> Element { + fn Child() -> Element { render!( div { "goodbye world" } ) } @@ -117,12 +117,12 @@ fn free_works_on_root_hooks() { } fn app(cx: Scope) -> Element { - let name: &AppProps = cx.use_hook(|| cx.props.clone()); + let name: &AppProps = cx.use_hook(|| cx.clone()); render!(child_component { inner: name.inner.clone() }) } fn child_component(cx: Scope) -> Element { - render!( div { "{cx.props.inner}" } ) + render!( div { "{cx.inner}" } ) } let ptr = Rc::new("asdasd".to_string()); @@ -143,8 +143,8 @@ fn supports_async() { use tokio::time::sleep; fn app() -> Element { - let colors = use_state(cx, || vec!["green", "blue", "red"]); - let padding = use_state(cx, || 10); + let colors = use_signal(|| vec!["green", "blue", "red"]); + let padding = use_signal(|| 10); use_effect(cx, colors, |colors| async move { sleep(Duration::from_millis(1000)).await; diff --git a/packages/core/tests/suspense.rs b/packages/core/tests/suspense.rs index b0dc743ed..6f04106b1 100644 --- a/packages/core/tests/suspense.rs +++ b/packages/core/tests/suspense.rs @@ -28,11 +28,10 @@ fn app() -> Element { ) } -fn suspended_child(cx: Scope) -> Element { - let val = use_state(cx, || 0); +fn suspended_child() -> Element { + let mut val = use_signal(|| 0); - if **val < 3 { - let mut val = val.clone(); + if *val() < 3 { cx.spawn(async move { val += 1; });