浏览代码

WIP macro progress

demonthos 3 年之前
父节点
当前提交
9e9fc09e6d
共有 3 个文件被更改,包括 163 次插入62 次删除
  1. 48 32
      packages/native-core-macro/src/lib.rs
  2. 110 25
      packages/native-core/src/real_dom_new_api.rs
  3. 5 5
      packages/native-core/tests/parse.rs

+ 48 - 32
packages/native-core-macro/src/lib.rs

@@ -36,6 +36,7 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
     };
     let strct = Struct::parse(&fields);
     let state_strct = StateStruct::parse(&fields, &strct);
+
     let node_dep_state_fields = quote::__private::TokenStream::from_iter(
         state_strct
             .state_members
@@ -86,67 +87,77 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
         .state_members
         .iter()
         .filter(|f| f.dep_kind == DepKind::NodeDepState)
-        .map(|f| f.type_id());
+        .map(|f| &f.mem.ty);
     let child_types = state_strct
         .state_members
         .iter()
         .filter(|f| f.dep_kind == DepKind::ChildDepState)
-        .map(|f| f.type_id());
+        .map(|f| &f.mem.ty);
     let parent_types = state_strct
         .state_members
         .iter()
         .filter(|f| f.dep_kind == DepKind::ParentDepState)
-        .map(|f| f.type_id());
+        .map(|f| &f.mem.ty);
 
     let type_name_str = type_name.to_string();
 
     let gen = quote! {
         impl State for #type_name{
-            fn update_node_dep_state(&mut self, ty: std::any::TypeId, node: dioxus_native_core::real_dom_new_api::NodeRef, ctx: &anymap::AnyMap){
+            fn update_node_dep_state<'a>(&'a mut self, ty: std::any::TypeId, node: &'a dioxus_core::VElement<'a>, ctx: &anymap::AnyMap) -> bool{
                 use dioxus_native_core::real_dom_new_api::NodeDepState;
-                if false {}
+                if false {
+                    unreachable!();
+                }
                 #node_dep_state_fields
                 else{
-                    panic!("{:?} not in {}", ty, #type_name_str);
+                    panic!("{:?} not in {}", ty, #type_name_str)
                 }
             }
 
-            fn update_parent_dep_state(&mut self, ty: std::any::TypeId, node: dioxus_native_core::real_dom_new_api::NodeRef, parent: &Self, ctx: &anymap::AnyMap){
+            fn update_parent_dep_state<'a>(&'a mut self, ty: std::any::TypeId, node: &'a dioxus_core::VElement<'a>, parent: &Self, ctx: &anymap::AnyMap) -> bool{
                 use dioxus_native_core::real_dom_new_api::ParentDepState;
-                if false {}
+                if false {
+                    unreachable!();
+                }
                 #parent_dep_state_fields
                 else{
-                    panic!("{:?} not in {}", ty, #type_name_str);
+                    panic!("{:?} not in {}", ty, #type_name_str)
                 }
             }
 
-            fn update_child_dep_state(&mut self, ty: std::any::TypeId, node: dioxus_native_core::real_dom_new_api::NodeRef, children: Vec<&Self>, ctx: &anymap::AnyMap){
+            fn update_child_dep_state<'a>(&'a mut self, ty: std::any::TypeId, node: &'a dioxus_core::VElement<'a>, children: Vec<&Self>, ctx: &anymap::AnyMap) -> bool{
                 use dioxus_native_core::real_dom_new_api::ChildDepState;
-                if false {}
+                if false {
+                    unreachable!()
+                }
                 #child_dep_state_fields
                 else{
-                    panic!("{:?} not in {}", ty, #type_name_str);
+                    panic!("{:?} not in {}", ty, #type_name_str)
                 }
             }
 
-            fn child_dep_types(&self) -> Vec<std::any::TypeId>{
-                // todo: order should depend on order of dependencies
-                vec![
-                    #(#child_types,)*
-                ]
+            fn child_dep_types(&self, mask: &dioxus_native_core::real_dom_new_api::NodeMask) -> Vec<std::any::TypeId>{
+                let mut dep_types = Vec::new();
+                #(if #child_types::NODE_MASK.overlaps(mask) {
+                    dep_types.push(std::any::TypeId::of::<#child_types>());
+                })*
+                dep_types
             }
 
-            fn parent_dep_types(&self) -> Vec<std::any::TypeId>{
-                // todo: order should depend on order of dependencies
-                vec![
-                    #(#parent_types,)*
-                ]
+            fn parent_dep_types(&self, mask: &dioxus_native_core::real_dom_new_api::NodeMask) -> Vec<std::any::TypeId>{
+                let mut dep_types = Vec::new();
+                #(if #parent_types::NODE_MASK.overlaps(mask) {
+                    dep_types.push(std::any::TypeId::of::<#parent_types>());
+                })*
+                dep_types
             }
 
-            fn node_dep_types(&self) -> Vec<std::any::TypeId>{
-                vec![
-                    #(#node_types,)*
-                ]
+            fn node_dep_types(&self, mask: &dioxus_native_core::real_dom_new_api::NodeMask) -> Vec<std::any::TypeId>{
+                let mut dep_types = Vec::new();
+                #(if #node_types::NODE_MASK.overlaps(mask) {
+                    dep_types.push(std::any::TypeId::of::<#node_types>());
+                })*
+                dep_types
             }
         }
     };
@@ -176,6 +187,9 @@ impl<'a> StateStruct<'a> {
             .zip(fields.iter())
             .filter_map(|(m, f)| StateMember::parse(f, m, &strct))
             .collect();
+
+        // todo: sort members
+
         Self { state_members }
     }
 }
@@ -251,28 +265,30 @@ impl<'a> StateMember<'a> {
         } else {
             quote! {&()}
         };
+        let ty = &self.mem.ty;
+        let node_view = quote!(NodeView::new(node, #ty::NODE_MASK));
         if let Some(dep_ident) = &self.dep_mem.map(|m| &m.ident) {
             match self.dep_kind {
                 DepKind::NodeDepState => {
-                    quote!(self.#ident.reduce(node, #get_ctx);)
+                    quote!(self.#ident.reduce(#node_view, #get_ctx))
                 }
                 DepKind::ChildDepState => {
-                    quote!(self.#ident.reduce(node, children.iter().map(|s| &s.#dep_ident).collect(), #get_ctx);)
+                    quote!(self.#ident.reduce(#node_view, children.iter().map(|s| &s.#dep_ident).collect(), #get_ctx))
                 }
                 DepKind::ParentDepState => {
-                    quote!(self.#ident.reduce(node, &parent.#dep_ident, #get_ctx);)
+                    quote!(self.#ident.reduce(#node_view, &parent.#dep_ident, #get_ctx))
                 }
             }
         } else {
             match self.dep_kind {
                 DepKind::NodeDepState => {
-                    quote!(self.#ident.reduce(node, #get_ctx);)
+                    quote!(self.#ident.reduce(#node_view, #get_ctx))
                 }
                 DepKind::ChildDepState => {
-                    quote!(self.#ident.reduce(node, &(), #get_ctx);)
+                    quote!(self.#ident.reduce(#node_view, &(), #get_ctx))
                 }
                 DepKind::ParentDepState => {
-                    quote!(self.#ident.reduce(node, &(), #get_ctx);)
+                    quote!(self.#ident.reduce(#node_view, &(), #get_ctx))
                 }
             }
         }

+ 110 - 25
packages/native-core/src/real_dom_new_api.rs

@@ -3,56 +3,141 @@ use std::any::TypeId;
 use anymap::AnyMap;
 use dioxus_core::{Attribute, VElement};
 
-#[repr(transparent)]
-pub struct NodeRef<'a>(&'a VElement<'a>);
-impl<'a> NodeRef<'a> {
-    pub fn new(velement: &'a VElement<'a>) -> Self {
-        Self(velement)
+pub struct NodeView<'a> {
+    inner: &'a VElement<'a>,
+    view: NodeMask,
+}
+impl<'a> NodeView<'a> {
+    pub fn new(velement: &'a VElement<'a>, view: NodeMask) -> Self {
+        Self {
+            inner: velement,
+            view: view,
+        }
     }
 
-    pub fn tag(&self) -> &'a str {
-        self.0.tag
+    pub fn tag(&self) -> Option<&'a str> {
+        if self.view.tag {
+            Some(self.inner.tag)
+        } else {
+            None
+        }
     }
 
     pub fn namespace(&self) -> Option<&'a str> {
-        self.0.namespace
+        if self.view.namespace {
+            self.inner.namespace
+        } else {
+            None
+        }
+    }
+
+    pub fn attributes(&self) -> impl Iterator<Item = &Attribute<'a>> {
+        self.inner
+            .attributes
+            .iter()
+            .filter(|a| self.view.attritutes.contains(&a.name))
+    }
+}
+
+#[derive(Default)]
+pub struct NodeMask {
+    // must be sorted
+    attritutes: &'static [&'static str],
+    tag: bool,
+    namespace: bool,
+}
+
+impl NodeMask {
+    /// attritutes must be sorted!
+    pub const fn new(attritutes: &'static [&'static str], tag: bool, namespace: bool) -> Self {
+        Self {
+            attritutes,
+            tag,
+            namespace,
+        }
     }
 
-    pub fn attributes(&self) -> &'a [Attribute<'a>] {
-        self.0.attributes
+    pub fn verify(&self) {
+        debug_assert!(
+            self.attritutes.windows(2).all(|w| w[0] < w[1]),
+            "attritutes must be increasing"
+        );
+    }
+
+    pub fn overlaps(&self, other: &Self) -> bool {
+        (self.tag && other.tag)
+            || (self.namespace && other.namespace)
+            || self.attritutes_overlap(other)
+    }
+
+    fn attritutes_overlap(&self, other: &Self) -> bool {
+        let mut self_attrs = self.attritutes.iter();
+        let mut other_attrs = other.attritutes.iter();
+        if let Some(mut other_attr) = other_attrs.next() {
+            while let Some(self_attr) = self_attrs.next() {
+                while other_attr < self_attr {
+                    if let Some(attr) = other_attrs.next() {
+                        other_attr = attr;
+                    } else {
+                        return false;
+                    }
+                }
+                if other_attr == self_attr {
+                    return true;
+                }
+            }
+        }
+        false
     }
 }
 
-pub trait ChildDepState: PartialEq {
+pub trait ChildDepState {
     type Ctx;
     type DepState: ChildDepState;
-    fn reduce(&mut self, node: NodeRef, children: Vec<&Self::DepState>, ctx: &Self::Ctx);
+    const NODE_MASK: NodeMask = NodeMask::new(&[], false, false);
+    fn reduce(&mut self, node: NodeView, children: Vec<&Self::DepState>, ctx: &Self::Ctx) -> bool;
 }
 
-pub trait ParentDepState: PartialEq {
+pub trait ParentDepState {
     type Ctx;
     type DepState: ParentDepState;
-    fn reduce(&mut self, node: NodeRef, parent: &Self::DepState, ctx: &Self::Ctx);
+    const NODE_MASK: NodeMask = NodeMask::new(&[], false, false);
+    fn reduce(&mut self, node: NodeView, parent: &Self::DepState, ctx: &Self::Ctx) -> bool;
 }
 
-pub trait NodeDepState: PartialEq {
+pub trait NodeDepState {
     type Ctx;
-    fn reduce(&mut self, node: NodeRef, ctx: &Self::Ctx);
+    const NODE_MASK: NodeMask = NodeMask::new(&[], false, false);
+    fn reduce(&mut self, node: NodeView, ctx: &Self::Ctx) -> bool;
 }
 
 pub trait State {
-    fn update_node_dep_state(&mut self, ty: TypeId, node: NodeRef, ctx: &AnyMap);
-    fn child_dep_types(&self) -> Vec<TypeId>;
+    fn update_node_dep_state<'a>(
+        &'a mut self,
+        ty: TypeId,
+        node: &'a VElement<'a>,
+        ctx: &AnyMap,
+    ) -> bool;
+    /// This must be a valid resolution order. (no nodes updated before a state they rely on)
+    fn child_dep_types(&self, mask: &NodeMask) -> Vec<TypeId>;
 
-    fn update_parent_dep_state(&mut self, ty: TypeId, node: NodeRef, parent: &Self, ctx: &AnyMap);
-    fn parent_dep_types(&self) -> Vec<TypeId>;
+    fn update_parent_dep_state<'a>(
+        &'a mut self,
+        ty: TypeId,
+        node: &'a VElement<'a>,
+        parent: &Self,
+        ctx: &AnyMap,
+    ) -> bool;
+    /// This must be a valid resolution order. (no nodes updated before a state they rely on)
+    fn parent_dep_types(&self, mask: &NodeMask) -> Vec<TypeId>;
 
-    fn update_child_dep_state(
-        &mut self,
+    fn update_child_dep_state<'a>(
+        &'a mut self,
         ty: TypeId,
-        node: NodeRef,
+        node: &'a VElement<'a>,
         children: Vec<&Self>,
         ctx: &AnyMap,
-    );
-    fn node_dep_types(&self) -> Vec<TypeId>;
+    ) -> bool;
+    /// This must be a valid resolution order. (no nodes updated before a state they rely on)
+    fn node_dep_types(&self, mask: &NodeMask) -> Vec<TypeId>;
 }

+ 5 - 5
packages/native-core/tests/parse.rs

@@ -26,7 +26,7 @@ use dioxus_native_core::real_dom_new_api::NodeDepState;
 struct A;
 impl NodeDepState for A {
     type Ctx = ();
-    fn reduce(&mut self, _: NodeRef, _: &()) {
+    fn reduce(&mut self, _: NodeView, _: &()) -> bool {
         todo!()
     }
 }
@@ -38,10 +38,10 @@ impl ChildDepState for B {
     type DepState = Self;
     fn reduce(
         &mut self,
-        _: dioxus_native_core::real_dom_new_api::NodeRef,
+        _: dioxus_native_core::real_dom_new_api::NodeView,
         _: Vec<&Self::DepState>,
         _: &i32,
-    ) {
+    ) -> bool {
         todo!()
     }
 }
@@ -53,10 +53,10 @@ impl ParentDepState for C {
     type DepState = Self;
     fn reduce(
         &mut self,
-        _: dioxus_native_core::real_dom_new_api::NodeRef,
+        _: dioxus_native_core::real_dom_new_api::NodeView,
         _: &Self::DepState,
         _: &u8,
-    ) {
+    ) -> bool {
         todo!()
     }
 }