From d96276a715a9f62943909cfc429c9fe47fd28146 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Sat, 6 Nov 2021 21:07:01 -0400 Subject: [PATCH] wip: no more lifetimes --- packages/core/src/component.rs | 4 ++-- packages/core/src/hooks.rs | 4 ++-- packages/core/src/lib.rs | 4 ++-- packages/core/src/nodes.rs | 20 ++++++++++++++++---- packages/core/src/scope.rs | 15 +++++++-------- packages/core/src/virtual_dom.rs | 16 +++++++++------- 6 files changed, 38 insertions(+), 25 deletions(-) diff --git a/packages/core/src/component.rs b/packages/core/src/component.rs index 8bcc8bd35..fceabb196 100644 --- a/packages/core/src/component.rs +++ b/packages/core/src/component.rs @@ -99,7 +99,7 @@ impl<'a> Properties for FragmentProps<'a> { /// You want to use this free-function when your fragment needs a key and simply returning multiple nodes from rsx! won't cut it. /// #[allow(non_upper_case_globals, non_snake_case)] -pub fn Fragment<'a>((cx, props): Scope<'a, FragmentProps<'a>>) -> Element<'a> { +pub fn Fragment<'a>((cx, props): Scope<'a, FragmentProps<'a>>) -> Element { cx.render(Some(LazyNodes::new(|f| { f.fragment_from_iter(&props.children) }))) @@ -170,6 +170,6 @@ 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<'a, T: Properties + 'a>(_: fn(Scope<'a, T>) -> Element<'a>) -> T::Builder { +pub fn fc_to_builder<'a, T: Properties + 'a>(_: fn(Scope<'a, T>) -> Element) -> T::Builder { T::builder() } diff --git a/packages/core/src/hooks.rs b/packages/core/src/hooks.rs index 54a5ca5a5..349011dae 100644 --- a/packages/core/src/hooks.rs +++ b/packages/core/src/hooks.rs @@ -95,11 +95,11 @@ pub fn use_suspense<'src, Out, Fut, Cb>( cx: Context<'src>, task_initializer: impl FnOnce() -> Fut, user_callback: Cb, -) -> Element<'src> +) -> Element where Fut: Future, Out: 'static, - Cb: FnMut(&Out) -> Element<'src> + 'src, + Cb: FnMut(&Out) -> Element + 'src, { /* General strategy: diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index 322f0d48a..26d13a078 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -48,8 +48,8 @@ pub(crate) mod innerlude { pub use crate::util::*; pub use crate::virtual_dom::*; - pub type Element<'a> = Option>; - pub type FC

= for<'a> fn(Scope<'a, P>) -> Element<'a>; + pub type Element = Option; + pub type FC

= for<'a> fn(Scope<'a, P>) -> CachedNode; } pub use crate::innerlude::{ diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs index 6c6def108..b100933b1 100644 --- a/packages/core/src/nodes.rs +++ b/packages/core/src/nodes.rs @@ -14,6 +14,18 @@ use std::{ fmt::{Arguments, Debug, Formatter}, }; +/// A cached node is a "pointer" to a "rendered" node in a particular scope +/// +/// It does not provide direct access to the node, so it doesn't carry any lifetime information with it +/// +/// It is used during the diffing/rendering process as a runtime key into an existing set of nodes. The "render" key +/// is essentially a unique key to guarantee safe usage of the Node. +pub struct CachedNode { + frame_id: u32, + gen_id: u32, + scope_id: ScopeId, +} + /// A composable "VirtualNode" to declare a User Interface in the Dioxus VirtualDOM. /// /// VNodes are designed to be lightweight and used with with a bump allocator. To create a VNode, you can use either of: @@ -335,8 +347,8 @@ pub struct VComponent<'src> { } pub enum VCompCaller<'src> { - Borrowed(BumpBox<'src, dyn for<'b> Fn(&'b ScopeInner) -> Element<'b> + 'src>), - Owned(Box Fn(&'b ScopeInner) -> Element<'b>>), + Borrowed(BumpBox<'src, dyn for<'b> Fn(&'b ScopeInner) -> Element + 'src>), + Owned(Box Fn(&'b ScopeInner) -> Element>), } pub struct VSuspended<'a> { @@ -344,7 +356,7 @@ pub struct VSuspended<'a> { pub dom_id: Cell>, #[allow(clippy::type_complexity)] - pub callback: RefCell Element<'a> + 'a>>>, + pub callback: RefCell Element + 'a>>>, } /// This struct provides an ergonomic API to quickly build VNodes. @@ -481,7 +493,7 @@ impl<'a> NodeFactory<'a> { pub fn component( &self, - component: fn(Scope<'a, P>) -> Element<'a>, + component: fn(Scope<'a, P>) -> Element, props: P, key: Option, ) -> VNode<'a> diff --git a/packages/core/src/scope.rs b/packages/core/src/scope.rs index c57cb6ba1..bab5abb09 100644 --- a/packages/core/src/scope.rs +++ b/packages/core/src/scope.rs @@ -173,7 +173,7 @@ impl ScopeInner { let sus: &'a VSuspended<'static> = unsafe { &*suspended }; let sus: &'a VSuspended<'a> = unsafe { std::mem::transmute(sus) }; let mut boxed = sus.callback.borrow_mut().take().unwrap(); - let new_node: Element<'a> = boxed(); + let new_node: Element = boxed(); } } @@ -366,13 +366,12 @@ impl ScopeInner { /// cx.render(lazy_tree) /// } ///``` - pub fn render<'src>( - &'src self, - lazy_nodes: Option>, - ) -> Option> { - let bump = &self.frames.wip_frame().bump; - let factory = NodeFactory { bump }; - lazy_nodes.map(|f| f.call(factory)) + pub fn render<'src>(&'src self, lazy_nodes: Option>) -> Option { + todo!() + // ) -> Option> { + // let bump = &self.frames.wip_frame().bump; + // let factory = NodeFactory { bump }; + // lazy_nodes.map(|f| f.call(factory)) } /// Push an effect to be ran after the component has been successfully mounted to the dom diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index a4650e2c2..adec57275 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -267,7 +267,8 @@ impl VirtualDom { let root_caller: Box Element> = Box::new(move |scope: &ScopeInner| unsafe { let props: &'_ P = &*(props_ptr as *const P); - std::mem::transmute(root((scope, props))) + Some(root((scope, props))) + // std::mem::transmute() }); drop(root_props); @@ -896,18 +897,19 @@ impl VirtualDom { // temporarily cast the vcomponent to the right lifetime let vcomp = scope.load_vcomp(); - let render: &dyn for<'b> Fn(&'b ScopeInner) -> Element<'b> = todo!(); + let render: &dyn Fn(&ScopeInner) -> Element = todo!(); // Todo: see if we can add stronger guarantees around internal bookkeeping and failed component renders. if let Some(builder) = render(scope) { - let new_head = builder.into_vnode(NodeFactory { - bump: &scope.frames.wip_frame().bump, - }); + todo!("attach the niode"); + // let new_head = builder.into_vnode(NodeFactory { + // bump: &scope.frames.wip_frame().bump, + // }); log::debug!("Render is successful"); // the user's component succeeded. We can safely cycle to the next frame - scope.frames.wip_frame_mut().head_node = unsafe { std::mem::transmute(new_head) }; - scope.frames.cycle_frame(); + // scope.frames.wip_frame_mut().head_node = unsafe { std::mem::transmute(new_head) }; + // scope.frames.cycle_frame(); true } else {