소스 검색

wip: remove send requirement on root props

Jonathan Kelley 3 년 전
부모
커밋
5a21493
3개의 변경된 파일39개의 추가작업 그리고 21개의 파일을 삭제
  1. 5 2
      README.md
  2. 19 2
      packages/core/src/scope.rs
  3. 15 17
      packages/core/src/virtual_dom.rs

+ 5 - 2
README.md

@@ -49,7 +49,7 @@
 Dioxus is a portable, performant, and ergonomic framework for building cross-platform user experiences in Rust.
 
 ```rust
-fn App((cx, props): Component<()>) -> Element {
+fn App((cx, props): Scope<()>) -> Element {
     let mut count = use_state(cx, || 0);
 
     cx.render(rsx!(
@@ -147,8 +147,11 @@ Dioxus is heavily inspired by React, but we want your transition to feel like an
 | Subtree Memoization       | ✅      | ❓     | skip diffing static element subtrees                                 |
 | Compile-time correct      | ✅      | ❓     | Throw errors on invalid template layouts                             |
 | Heuristic Engine          | ✅      | ❓     | track component memory usage to minimize future allocations          |
-| Fine-grained reactivity   | 🛠      | ❓     | Skip diffing for fine-grain updates                                  |
 | Effects                   | 🛠      | ✅     | Run effects after a component has been committed to render           |
+| Server Components         | 🛠      | ✅     | Hybrid components for SPA and Server                                 |
+| Bundle Splitting          | 👀      | ✅     | Hybrid components for SPA and Server                                 |
+| Lazy Components           | 👀      | ✅     | Dynamically load the new components as the page is loaded            |
+| Fine-grained reactivity   | 👀      | ❓     | Skip diffing for fine-grain updates                                  |
 
 - ✅ = implemented and working
 - 🛠 = actively being worked on

+ 19 - 2
packages/core/src/scope.rs

@@ -210,9 +210,9 @@ impl ScopeInner {
         }
     }
 
-    pub(crate) fn update_scope_dependencies<'creator_node>(
+    pub(crate) fn update_scope_dependencies(
         &mut self,
-        caller: &'creator_node dyn for<'b> Fn(&'b ScopeInner) -> Element<'b>,
+        caller: &dyn for<'b> Fn(&'b ScopeInner) -> Element<'b>,
     ) {
         log::debug!("Updating scope dependencies {:?}", self.our_arena_idx);
         let caller = caller as *const _;
@@ -308,6 +308,23 @@ impl ScopeInner {
         }
     }
 
+    // run the list of effects
+    pub(crate) fn run_effects(&mut self, pool: &ResourcePool) {
+        todo!()
+        // let mut effects = self.frames.effects.borrow_mut();
+        // let mut effects = effects.drain(..).collect::<Vec<_>>();
+
+        // for effect in effects {
+        //     let effect = unsafe { &*effect };
+        //     let effect = effect.as_ref();
+
+        //     let mut effect = effect.borrow_mut();
+        //     let mut effect = effect.as_mut();
+
+        //     effect.run(pool);
+        // }
+    }
+
     /// Render this component.
     ///
     /// Returns true if the scope completed successfully and false if running failed (IE a None error was propagated).

+ 15 - 17
packages/core/src/virtual_dom.rs

@@ -61,10 +61,10 @@ pub struct VirtualDom {
 
     root_fc: Box<dyn Any>,
 
-    root_props: Rc<dyn Any + Send>,
+    root_props: Rc<dyn Any>,
 
     // we need to keep the allocation around, but we don't necessarily use it
-    _root_caller: RootCaller,
+    _root_caller: Rc<dyn Any>,
 }
 
 impl VirtualDom {
@@ -131,7 +131,7 @@ impl VirtualDom {
     ///
     /// This is useful when the VirtualDom must be driven from outside a thread and it doesn't make sense to wait for the
     /// VirtualDom to be created just to retrieve its channel receiver.
-    pub fn new_with_props_and_scheduler<P: 'static + Send>(
+    pub fn new_with_props_and_scheduler<P: 'static>(
         root: FC<P>,
         root_props: P,
         sender: UnboundedSender<SchedulerMsg>,
@@ -139,15 +139,16 @@ impl VirtualDom {
     ) -> Self {
         let root_fc = Box::new(root);
 
-        let root_props: Rc<dyn Any + Send> = Rc::new(root_props);
+        let root_props: Rc<dyn Any> = Rc::new(root_props);
 
-        let _p = root_props.clone();
-        // Safety: this callback is only valid for the lifetime of the root props
-        let root_caller: Rc<dyn Fn(&ScopeInner) -> Element> =
-            Rc::new(move |scope: &ScopeInner| unsafe {
-                let props = _p.downcast_ref::<P>().unwrap();
-                std::mem::transmute(root((Context { scope }, props)))
-            });
+        let props = root_props.clone();
+
+        let root_caller: Rc<dyn Fn(&ScopeInner) -> Element> = Rc::new(move |scope: &ScopeInner| {
+            let props = props.downcast_ref::<P>().unwrap();
+            let node = root((Context { scope }, props));
+            // cast into the right lifetime
+            unsafe { std::mem::transmute(node) }
+        });
 
         let scheduler = Scheduler::new(sender, receiver);
 
@@ -163,7 +164,7 @@ impl VirtualDom {
         });
 
         Self {
-            _root_caller: RootCaller(root_caller),
+            _root_caller: Rc::new(root_caller),
             root_fc,
             base_scope,
             scheduler,
@@ -204,14 +205,14 @@ impl VirtualDom {
     /// ```
     pub fn update_root_props<P>(&mut self, root_props: P) -> Option<Mutations>
     where
-        P: 'static + Send,
+        P: 'static,
     {
         let root_scope = self.scheduler.pool.get_scope_mut(self.base_scope).unwrap();
 
         // Pre-emptively drop any downstream references of the old props
         root_scope.ensure_drop_safety(&self.scheduler.pool);
 
-        let mut root_props: Rc<dyn Any + Send> = Rc::new(root_props);
+        let mut root_props: Rc<dyn Any> = Rc::new(root_props);
 
         if let Some(props_ptr) = root_props.downcast_ref::<P>().map(|p| p as *const P) {
             // Swap the old props and new props
@@ -394,6 +395,3 @@ impl VirtualDom {
         }
     }
 }
-
-// we never actually use the contents of this root caller
-struct RootCaller(Rc<dyn for<'b> Fn(&'b ScopeInner) -> Element<'b> + 'static>);