1
0
Эх сурвалжийг харах

wip: allow async into component

Jonathan Kelley 2 жил өмнө
parent
commit
591674f701

+ 17 - 12
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<P, F: Future<Output = ()> = Dummy> {
-    pub render_fn: ComponentFn<P, F>,
+pub(crate) struct VComponentProps<'a, P, F: Future<Output = Element<'a>> = 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<P> VComponentProps<P> {
+impl<P> VComponentProps<'_, P> {
     pub(crate) fn new(
         render_fn: Component<P>,
         memo: unsafe fn(&P, &P) -> bool,
@@ -42,7 +42,7 @@ impl<P> VComponentProps<P> {
     }
 }
 
-impl<P> AnyProps for VComponentProps<P> {
+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<P> AnyProps for VComponentProps<P> {
         (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<P> AnyProps for VComponentProps<P> {
 
         // 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!()
     }
 }

+ 16 - 14
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<T = ()> = fn(Scope<T>) -> Element;
 
-pub enum ComponentFn<T, F: Future<Output = ()> = Dummy> {
-    Sync(fn(Scope<T>) -> Element),
-    Async(fn(Scope<T>) -> F),
+pub enum ComponentFn<'a, T, F: Future<Output = Element<'a>> = Dummy<'a>> {
+    Sync(fn(Scope<'a, T>) -> Element),
+    Async(fn(Scope<'a, T>) -> F),
 }
 
-pub trait IntoComponent<T, A = ()> {
-    fn into_component(self) -> ComponentFn<T>;
+pub trait IntoComponent<'a, T, F: Future<Output = Element<'a>> = Dummy<'a>, A = ()> {
+    fn into_component(self) -> ComponentFn<'a, T, F>;
 }
 
-impl<T> IntoComponent<T> for fn(Scope<T>) -> Element {
-    fn into_component(self) -> ComponentFn<T> {
+impl<'a, T> IntoComponent<'a, T, Dummy<'a>> for fn(Scope<T>) -> Element {
+    fn into_component(self) -> ComponentFn<'a, T> {
         ComponentFn::Sync(self)
     }
 }
 
 pub struct AsyncMarker;
-impl<'a, T, F: Future<Output = Element<'a>>> IntoComponent<T, AsyncMarker>
-    for fn(&'a Scope<T>) -> F
+impl<'a, T, F: Future<Output = Element<'a>>> IntoComponent<'a, T, F, AsyncMarker>
+    for fn(Scope<'a, T>) -> F
 {
-    fn into_component(self) -> ComponentFn<T> {
-        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>,

+ 1 - 1
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);
 

+ 8 - 0
packages/core/src/diff.rs

@@ -24,4 +24,12 @@ impl VirtualDom {
     fn diff_scope<'a>(&'a mut self, mutations: &mut Vec<Mutation<'a>>, scope: ScopeId) {
         let scope_state = &mut self.scopes[scope.0];
     }
+
+    fn diff_template<'a>(
+        &'a mut self,
+        mutations: &mut Vec<Mutation<'a>>,
+        left: &VNode,
+        right: &VNode,
+    ) {
+    }
 }

+ 1 - 1
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

+ 9 - 6
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,

+ 1 - 1
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 {