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

wip: working on re-enabling components

Jonathan Kelley 3 жил өмнө
parent
commit
fffc7ea

+ 1 - 0
packages/core/examples/works.rs

@@ -13,6 +13,7 @@ fn Parent(cx: Context, props: &()) -> Element {
     cx.render(rsx! {
         div {
             Child { name: value }
+            Fragment { "asd" }
         }
     })
 }

+ 1 - 1
packages/core/src/component.rs

@@ -137,7 +137,7 @@ 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(Context<'a>, &T) -> Element) -> T::Builder {
+pub fn fc_to_builder<'a, T: Properties + 'a>(_: fn(Context<'a>, &'a T) -> Element) -> T::Builder {
     // pub fn fc_to_builder<'a, T: Properties + 'a>(_: fn(Scope<'a, T>) -> Element) -> T::Builder {
     T::builder()
 }

+ 69 - 74
packages/core/src/nodes.rs

@@ -531,89 +531,84 @@ impl<'a> NodeFactory<'a> {
         - if the props aren't static, then we convert them into a box which we pass off between renders
         */
 
-        let bump = self.bump();
-
-        // later, we'll do a hard allocation
-        let raw_ptr = bump.alloc(props);
-        // let caller = Box::new(|f: &ScopeInner| -> Element {
-        //     //
-        //     component((f, &props))
-        // });
+        // let bump = self.bump();
 
+        // // later, we'll do a hard allocation
+        // let raw_ptr = bump.alloc(props);
+        let bump = self.bump();
+        let props = bump.alloc(props);
+        let bump_props = props as *mut P as *mut ();
         let user_fc = component as *const ();
 
-        // let comparator: &mut dyn Fn(&VComponent) -> bool = bump.alloc_with(|| {
-        //     move |other: &VComponent| {
-        //         if user_fc == other.user_fc {
-        //             // Safety
-        //             // - We guarantee that FC<P> is the same by function pointer
-        //             // - Because FC<P> is the same, then P must be the same (even with generics)
-        //             // - Non-static P are autoderived to memoize as false
-        //             // - This comparator is only called on a corresponding set of bumpframes
-        //             let props_memoized = unsafe {
-        //                 let real_other: &P = &*(other.raw_props as *const _ as *const P);
-        //                 props.memoize(real_other)
-        //             };
-
-        //             // It's only okay to memoize if there are no children and the props can be memoized
-        //             // Implementing memoize is unsafe and done automatically with the props trait
-        //             props_memoized
-        //         } else {
-        //             false
-        //         }
-        //     }
-        // });
-        // let comparator = Some(unsafe { BumpBox::from_raw(comparator) });
+        let comparator: &mut dyn Fn(&VComponent) -> bool = bump.alloc_with(|| {
+            move |other: &VComponent| {
+                if user_fc == other.user_fc {
+                    // Safety
+                    // - We guarantee that FC<P> is the same by function pointer
+                    // - Because FC<P> is the same, then P must be the same (even with generics)
+                    // - Non-static P are autoderived to memoize as false
+                    // - This comparator is only called on a corresponding set of bumpframes
+                    let props_memoized = unsafe {
+                        let real_other: &P = &*(other.bump_props as *const _ as *const P);
+                        props.memoize(real_other)
+                    };
+
+                    // It's only okay to memoize if there are no children and the props can be memoized
+                    // Implementing memoize is unsafe and done automatically with the props trait
+                    props_memoized
+                } else {
+                    false
+                }
+            }
+        });
 
-        let key = key.map(|f| self.raw_text(f).0);
+        let drop_props = {
+            // create a closure to drop the props
+            let mut has_dropped = false;
 
-        // let caller = match P::IS_STATIC {
-        //     true => {
-        //         // it just makes sense to box the props
-        //         let boxed_props: Box<P> = Box::new(props);
-        //         let props_we_know_are_static = todo!();
-        //         VCompCaller::Owned(Box::new(|f| {
-        //             //
+            let drop_props: &mut dyn FnMut() = bump.alloc_with(|| {
+                move || unsafe {
+                    log::debug!("dropping props!");
+                    if !has_dropped {
+                        let real_other = bump_props as *mut _ as *mut P;
+                        let b = BumpBox::from_raw(real_other);
+                        std::mem::drop(b);
 
-        //             let p = todo!();
+                        has_dropped = true;
+                    } else {
+                        panic!("Drop props called twice - this is an internal failure of Dioxus");
+                    }
+                }
+            });
 
-        //             todo!()
-        //         }))
-        //     }
-        //     false => VCompCaller::Borrowed({
-        //         //
+            let drop_props = unsafe { BumpBox::from_raw(drop_props) };
 
-        //         todo!()
-        //         // let caller = bump.alloc()
-        //     }),
-        // };
+            RefCell::new(Some(drop_props))
+        };
 
-        todo!()
-        // let caller: &'a mut dyn for<'b> Fn(&'b ScopeInner) -> Element<'b> =
-        //     bump.alloc(move |scope: &ScopeInner| -> Element {
-        //         log::debug!("calling component renderr {:?}", scope.our_arena_idx);
-        //         let props: &'_ P = unsafe { &*(raw_props as *const P) };
-
-        //         let scp: &'a ScopeInner = unsafe { std::mem::transmute(scope) };
-        //         let s: Scope<'a, P> = (scp, props);
-
-        //         let res: Element = component(s);
-        //         unsafe { std::mem::transmute(res) }
-        //     });
-
-        // let caller = unsafe { BumpBox::from_raw(caller) };
-
-        // VNode::Component(bump.alloc(VComponent {
-        //     user_fc,
-        //     comparator,
-        //     raw_props,
-        //     caller,
-        //     is_static: P::IS_STATIC,
-        //     key,
-        //     can_memoize: P::IS_STATIC,
-        //     drop_props,
-        //     associated_scope: Cell::new(None),
-        // }))
+        let key = key.map(|f| self.raw_text(f).0);
+
+        let caller: &'a mut dyn Fn(&Scope) -> Element =
+            bump.alloc(move |scope: &Scope| -> Element {
+                log::debug!("calling component renderr {:?}", scope.our_arena_idx);
+                let props: &'_ P = unsafe { &*(bump_props as *const P) };
+                let res = component(scope, props);
+                // let res = component((Context { scope }, props));
+                unsafe { std::mem::transmute(res) }
+            });
+
+        let can_memoize = P::IS_STATIC;
+
+        VNode::Component(bump.alloc(VComponent {
+            user_fc,
+            comparator,
+            bump_props,
+            caller,
+            key,
+            can_memoize,
+            drop_props,
+            associated_scope: Cell::new(None),
+        }))
     }
 
     pub fn listener(

+ 4 - 4
packages/core/tests/create_dom.rs

@@ -64,10 +64,10 @@ fn create() {
                     "Hello, world!"
                     div {
                         div {
-                            // Fragment {
-                            //     "hello"
-                            //     "world"
-                            // }
+                            Fragment {
+                                "hello"
+                                "world"
+                            }
                         }
                     }
                 }