فهرست منبع

unbox component functions

Evan Almloff 1 سال پیش
والد
کامیت
ef553a2cb2
4فایلهای تغییر یافته به همراه20 افزوده شده و 14 حذف شده
  1. 12 7
      packages/core/src/any_props.rs
  2. 0 1
      packages/core/src/nodes.rs
  3. 3 3
      packages/core/src/properties.rs
  4. 5 3
      packages/core/src/virtual_dom.rs

+ 12 - 7
packages/core/src/any_props.rs

@@ -1,5 +1,5 @@
 use crate::{nodes::RenderReturn, properties::ComponentFunction};
-use std::{any::Any, ops::Deref, panic::AssertUnwindSafe, rc::Rc};
+use std::{any::Any, marker::PhantomData, ops::Deref, panic::AssertUnwindSafe};
 
 /// A boxed version of AnyProps that can be cloned
 pub(crate) struct BoxedAnyProps {
@@ -38,30 +38,34 @@ pub(crate) trait AnyProps {
     fn duplicate(&self) -> Box<dyn AnyProps>;
 }
 
-pub(crate) struct VProps<P: 'static, Phantom: 'static> {
-    pub render_fn: Rc<dyn ComponentFunction<Phantom, Props = P>>,
+pub(crate) struct VProps<P: 'static, F: ComponentFunction<Phantom, Props = P>, Phantom: 'static> {
+    pub render_fn: F,
     pub memo: fn(&P, &P) -> bool,
     pub props: P,
     pub name: &'static str,
+    phantom: PhantomData<Phantom>,
 }
 
-impl<P: 'static, Phantom: 'static> VProps<P, Phantom> {
+impl<P: 'static, F: ComponentFunction<Phantom, Props = P>, Phantom: 'static> VProps<P, F, Phantom> {
     pub(crate) fn new(
-        render_fn: impl ComponentFunction<Phantom, Props = P> + 'static,
+        render_fn: F,
         memo: fn(&P, &P) -> bool,
         props: P,
         name: &'static str,
     ) -> Self {
         Self {
-            render_fn: Rc::new(render_fn),
+            render_fn,
             memo,
             props,
             name,
+            phantom: PhantomData,
         }
     }
 }
 
-impl<P: Clone + 'static, Phantom> AnyProps for VProps<P, Phantom> {
+impl<P: Clone + 'static, F: ComponentFunction<Phantom, Props = P>, Phantom> AnyProps
+    for VProps<P, F, Phantom>
+{
     fn memoize(&self, other: &dyn Any) -> bool {
         match other.downcast_ref::<P>() {
             Some(other) => (self.memo)(&self.props, other),
@@ -96,6 +100,7 @@ impl<P: Clone + 'static, Phantom> AnyProps for VProps<P, Phantom> {
             memo: self.memo,
             props: self.props.clone(),
             name: self.name,
+            phantom: PhantomData,
         })
     }
 }

+ 0 - 1
packages/core/src/nodes.rs

@@ -503,7 +503,6 @@ impl Default for DynamicNode {
     }
 }
 
-#[derive(Clone)]
 /// An instance of a child component
 pub struct VComponent {
     /// The name of this component

+ 3 - 3
packages/core/src/properties.rs

@@ -112,7 +112,7 @@ where
 /// ```
 ///
 /// > Note: If you get an error about the `ComponentFunction` trait not being implemented: make sure your props implements the `Properties` trait or if you would like to declare your props inline, make sure you use the #[component] macro on your function.
-pub trait ComponentFunction<P> {
+pub trait ComponentFunction<P>: Clone + 'static {
     /// The props type for this component.
     type Props: 'static;
 
@@ -120,7 +120,7 @@ pub trait ComponentFunction<P> {
     fn call(&self, props: Self::Props) -> Element;
 }
 
-impl<T: 'static, F: Fn(T) -> Element> ComponentFunction<(T,)> for F {
+impl<T: 'static, F: Fn(T) -> Element + Clone + 'static> ComponentFunction<(T,)> for F {
     type Props = T;
 
     fn call(&self, props: T) -> Element {
@@ -130,7 +130,7 @@ impl<T: 'static, F: Fn(T) -> Element> ComponentFunction<(T,)> for F {
 
 #[doc(hidden)]
 pub struct ZeroElementMarker;
-impl<F: Fn() -> Element> ComponentFunction<ZeroElementMarker> for F {
+impl<F: Fn() -> Element + Clone + 'static> ComponentFunction<ZeroElementMarker> for F {
     type Props = ();
 
     fn call(&self, _: ()) -> Element {

+ 5 - 3
packages/core/src/virtual_dom.rs

@@ -13,7 +13,7 @@ use crate::{
     nodes::{Template, TemplateId},
     runtime::{Runtime, RuntimeGuard},
     scopes::ScopeId,
-    AttributeValue, Element, Event, Mutations,
+    AttributeValue, BoxedContext, Element, Event, Mutations,
 };
 use futures_util::{pin_mut, StreamExt};
 use rustc_hash::{FxHashMap, FxHashSet};
@@ -328,8 +328,10 @@ impl VirtualDom {
     /// Build the virtualdom with a global context inserted into the base scope
     ///
     /// This method is useful for when you want to provide a context in your app without knowing its type
-    pub fn with_boxed_root_context(self, context: Box<dyn Any>) -> Self {
-        self.base_scope().context().provide_any_context(context);
+    pub fn with_boxed_root_context(self, context: BoxedContext) -> Self {
+        self.base_scope()
+            .context()
+            .provide_any_context(context.into_inner());
         self
     }