From 591674f701d4c8bd3b8bf4adbb78b00334485148 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Thu, 3 Nov 2022 02:11:04 -0700 Subject: [PATCH] wip: allow async into component --- packages/core/src/any_props.rs | 29 +++++++++++++++++------------ packages/core/src/component.rs | 30 ++++++++++++++++-------------- packages/core/src/create.rs | 2 +- packages/core/src/diff.rs | 8 ++++++++ packages/core/src/nodes.rs | 2 +- packages/core/src/scope_arena.rs | 15 +++++++++------ packages/core/src/scopes.rs | 2 +- 7 files changed, 53 insertions(+), 35 deletions(-) diff --git a/packages/core/src/any_props.rs b/packages/core/src/any_props.rs index 60187e458..543d05d31 100644 --- a/packages/core/src/any_props.rs +++ b/packages/core/src/any_props.rs @@ -6,19 +6,19 @@ use crate::{ Element, }; -pub trait AnyProps { +pub trait AnyProps<'a> { fn as_ptr(&self) -> *const (); - fn render<'a>(&'a self, bump: &'a ScopeState) -> Element<'a>; + fn render(&'a self, bump: &'a ScopeState) -> Element<'a>; unsafe fn memoize(&self, other: &dyn AnyProps) -> bool; } -pub(crate) struct VComponentProps = Dummy> { - pub render_fn: ComponentFn, +pub(crate) struct VComponentProps<'a, P, F: Future> = Dummy<'a>> { + pub render_fn: ComponentFn<'a, P, F>, pub memo: unsafe fn(&P, &P) -> bool, pub props: *const P, } -impl VComponentProps<()> { +impl VComponentProps<'_, ()> { pub fn new_empty(render_fn: Component<()>) -> Self { Self { render_fn: render_fn.into_component(), @@ -28,7 +28,7 @@ impl VComponentProps<()> { } } -impl

VComponentProps

{ +impl

VComponentProps<'_, P> { pub(crate) fn new( render_fn: Component

, memo: unsafe fn(&P, &P) -> bool, @@ -42,7 +42,7 @@ impl

VComponentProps

{ } } -impl

AnyProps for VComponentProps

{ +impl<'a, P> AnyProps<'a> for VComponentProps<'a, P> { fn as_ptr(&self) -> *const () { &self.props as *const _ as *const () } @@ -57,7 +57,7 @@ impl

AnyProps for VComponentProps

{ (self.memo)(real_us, real_other) } - fn render<'a>(&'a self, scope: &'a ScopeState) -> Element<'a> { + fn render<'b>(&'b self, scope: &'b ScopeState) -> Element<'b> { // Make sure the scope ptr is not null // self.props.state.set(scope); @@ -68,9 +68,14 @@ impl

AnyProps for VComponentProps

{ // Call the render function directly // todo: implement async - match self.render_fn { - ComponentFn::Sync(f) => f(scope), - ComponentFn::Async(_) => todo!(), - } + // let res = match self.render_fn { + // ComponentFn::Sync(f) => { + // let f = unsafe { std::mem::transmute(f) }; + // f(scope) + // } + // ComponentFn::Async(_) => todo!(), + // }; + + todo!() } } diff --git a/packages/core/src/component.rs b/packages/core/src/component.rs index 75b9e6b2d..145b4ca6c 100644 --- a/packages/core/src/component.rs +++ b/packages/core/src/component.rs @@ -2,39 +2,41 @@ // fn into_component_type(self) -> ComponentType; // } +use std::marker::PhantomData; + use futures_util::Future; use crate::{scopes::Scope, Element}; pub type Component = fn(Scope) -> Element; -pub enum ComponentFn = Dummy> { - Sync(fn(Scope) -> Element), - Async(fn(Scope) -> F), +pub enum ComponentFn<'a, T, F: Future> = Dummy<'a>> { + Sync(fn(Scope<'a, T>) -> Element), + Async(fn(Scope<'a, T>) -> F), } -pub trait IntoComponent { - fn into_component(self) -> ComponentFn; +pub trait IntoComponent<'a, T, F: Future> = Dummy<'a>, A = ()> { + fn into_component(self) -> ComponentFn<'a, T, F>; } -impl IntoComponent for fn(Scope) -> Element { - fn into_component(self) -> ComponentFn { +impl<'a, T> IntoComponent<'a, T, Dummy<'a>> for fn(Scope) -> Element { + fn into_component(self) -> ComponentFn<'a, T> { ComponentFn::Sync(self) } } pub struct AsyncMarker; -impl<'a, T, F: Future>> IntoComponent - for fn(&'a Scope) -> F +impl<'a, T, F: Future>> IntoComponent<'a, T, F, AsyncMarker> + for fn(Scope<'a, T>) -> F { - fn into_component(self) -> ComponentFn { - todo!() + fn into_component(self) -> ComponentFn<'a, T, F> { + ComponentFn::Async(self) } } -pub struct Dummy; -impl Future for Dummy { - type Output = (); +pub struct Dummy<'a>(PhantomData<&'a ()>); +impl<'a> Future for Dummy<'a> { + type Output = Element<'a>; fn poll( self: std::pin::Pin<&mut Self>, diff --git a/packages/core/src/create.rs b/packages/core/src/create.rs index ae9f6a7e2..dbb736cc6 100644 --- a/packages/core/src/create.rs +++ b/packages/core/src/create.rs @@ -170,7 +170,7 @@ impl VirtualDom { } DynamicNode::Component { props, .. } => { - let id = self.new_scope(*props); + let id = self.new_scope(unsafe { std::mem::transmute(*props) }); let template = self.run_scope(id); diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index 43b454c8b..0fe810a7e 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -24,4 +24,12 @@ impl VirtualDom { fn diff_scope<'a>(&'a mut self, mutations: &mut Vec>, scope: ScopeId) { let scope_state = &mut self.scopes[scope.0]; } + + fn diff_template<'a>( + &'a mut self, + mutations: &mut Vec>, + left: &VNode, + right: &VNode, + ) { + } } diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs index 39077dd1e..9eca083cf 100644 --- a/packages/core/src/nodes.rs +++ b/packages/core/src/nodes.rs @@ -78,7 +78,7 @@ pub enum DynamicNode<'a> { Component { name: &'static str, can_memoize: bool, - props: *mut dyn AnyProps, + props: *mut dyn AnyProps<'a>, }, // Comes in with string interpolation or from format_args, include_str, etc diff --git a/packages/core/src/scope_arena.rs b/packages/core/src/scope_arena.rs index 1bf90530d..8cb3aa5a1 100644 --- a/packages/core/src/scope_arena.rs +++ b/packages/core/src/scope_arena.rs @@ -8,7 +8,7 @@ use crate::{ }; impl VirtualDom { - pub fn new_scope(&mut self, props: *mut dyn AnyProps) -> ScopeId { + pub fn new_scope(&mut self, props: *mut dyn AnyProps<'static>) -> ScopeId { let parent = self.acquire_current_scope_raw(); let container = self.acquire_current_container(); let entry = self.scopes.vacant_entry(); @@ -48,14 +48,17 @@ impl VirtualDom { .and_then(|id| self.scopes.get_mut(id.0).map(|f| f as *mut ScopeState)) } - pub fn run_scope<'a>(&'a mut self, id: ScopeId) -> &'a VNode<'a> { + pub fn run_scope(&mut self, id: ScopeId) -> &VNode { let scope = &mut self.scopes[id.0]; scope.hook_idx.set(0); - let props = unsafe { &mut *scope.props }; - - let res = props.render(scope).unwrap(); - let res: VNode<'static> = unsafe { std::mem::transmute(res) }; + let res = { + let props = unsafe { &mut *scope.props }; + let props: &mut dyn AnyProps = unsafe { std::mem::transmute(props) }; + let res: VNode = props.render(scope).unwrap(); + let res: VNode<'static> = unsafe { std::mem::transmute(res) }; + res + }; let frame = match scope.render_cnt % 2 { 0 => &mut scope.node_arena_1, diff --git a/packages/core/src/scopes.rs b/packages/core/src/scopes.rs index deba70f6a..fe73bbbbb 100644 --- a/packages/core/src/scopes.rs +++ b/packages/core/src/scopes.rs @@ -66,7 +66,7 @@ pub struct ScopeState { pub tasks: FutureQueue, - pub props: *mut dyn AnyProps, + pub props: *mut dyn AnyProps<'static>, } impl ScopeState {