Преглед изворни кода

Merge pull request #708 from Demonthos/support-optional-attrtibutes

Support optional attributes
Jon Kelley пре 2 година
родитељ
комит
35cccc3838

+ 12 - 3
packages/core/src/nodes.rs

@@ -5,7 +5,7 @@ use bumpalo::boxed::Box as BumpBox;
 use bumpalo::Bump;
 use std::{
     any::{Any, TypeId},
-    cell::{self, Cell, RefCell, UnsafeCell},
+    cell::{Cell, RefCell, UnsafeCell},
     fmt::{Arguments, Debug},
     future::Future,
 };
@@ -611,7 +611,7 @@ impl PartialEq for BorrowedAttributeValue<'_> {
 }
 
 #[cfg(feature = "serialize")]
-fn serialize_any_value<S>(_: &cell::Ref<'_, dyn AnyValue>, _: S) -> Result<S::Ok, S::Error>
+fn serialize_any_value<S>(_: &std::cell::Ref<'_, dyn AnyValue>, _: S) -> Result<S::Ok, S::Error>
 where
     S: serde::Serializer,
 {
@@ -619,7 +619,7 @@ where
 }
 
 #[cfg(feature = "serialize")]
-fn deserialize_any_value<'de, 'a, D>(_: D) -> Result<cell::Ref<'a, dyn AnyValue>, D::Error>
+fn deserialize_any_value<'de, 'a, D>(_: D) -> Result<std::cell::Ref<'a, dyn AnyValue>, D::Error>
 where
     D: serde::Deserializer<'de>,
 {
@@ -888,3 +888,12 @@ impl<'a> IntoAttributeValue<'a> for BumpBox<'a, dyn AnyValue> {
         AttributeValue::Any(RefCell::new(Some(self)))
     }
 }
+
+impl<'a, T: IntoAttributeValue<'a>> IntoAttributeValue<'a> for Option<T> {
+    fn into_value(self, bump: &'a Bump) -> AttributeValue<'a> {
+        match self {
+            Some(val) => val.into_value(bump),
+            None => AttributeValue::None,
+        }
+    }
+}

+ 9 - 5
packages/interpreter/src/interpreter.js

@@ -144,8 +144,15 @@ class Interpreter {
     this.nodes[root].textContent = text;
   }
   SetAttribute(id, field, value, ns) {
-    const node = this.nodes[id];
-    this.SetAttributeInner(node, field, value, ns);
+    console.log("set attribute", id, field, value, ns);
+
+    if (value === null) {
+      this.RemoveAttribute(id, field, ns);
+    }
+    else {
+      const node = this.nodes[id];
+      this.SetAttributeInner(node, field, value, ns);
+    }
   }
   SetAttributeInner(node, field, value, ns) {
     const name = field;
@@ -334,9 +341,6 @@ class Interpreter {
       case "SetAttribute":
         this.SetAttribute(edit.id, edit.name, edit.value, edit.ns);
         break;
-      case "SetBoolAttribute":
-        this.SetAttribute(edit.id, edit.name, edit.value, edit.ns);
-        break;
       case "RemoveAttribute":
         this.RemoveAttribute(edit.id, edit.name, edit.ns);
         break;

+ 1 - 10
packages/native-core/src/node.rs

@@ -80,7 +80,6 @@ pub enum OwnedAttributeValue<V: FromAnyValue = ()> {
     Int(i64),
     Bool(bool),
     Custom(V),
-    None,
 }
 
 pub trait FromAnyValue {
@@ -99,7 +98,6 @@ impl<V: FromAnyValue> Debug for OwnedAttributeValue<V> {
             Self::Int(arg0) => f.debug_tuple("Int").field(arg0).finish(),
             Self::Bool(arg0) => f.debug_tuple("Bool").field(arg0).finish(),
             Self::Custom(_) => f.debug_tuple("Any").finish(),
-            Self::None => write!(f, "None"),
         }
     }
 }
@@ -112,7 +110,7 @@ impl<V: FromAnyValue> From<BorrowedAttributeValue<'_>> for OwnedAttributeValue<V
             BorrowedAttributeValue::Int(int) => Self::Int(int),
             BorrowedAttributeValue::Bool(bool) => Self::Bool(bool),
             BorrowedAttributeValue::Any(any) => Self::Custom(V::from_any_value(&*any)),
-            BorrowedAttributeValue::None => Self::None,
+            BorrowedAttributeValue::None => panic!("None attribute values result in removing the attribute, not converting it to a None value.")
         }
     }
 }
@@ -146,13 +144,6 @@ impl<V: FromAnyValue> OwnedAttributeValue<V> {
         }
     }
 
-    pub fn as_none(&self) -> Option<()> {
-        match self {
-            OwnedAttributeValue::None => Some(()),
-            _ => None,
-        }
-    }
-
     pub fn as_custom(&self) -> Option<&V> {
         match self {
             OwnedAttributeValue::Custom(custom) => Some(custom),

+ 24 - 11
packages/native-core/src/real_dom.rs

@@ -1,4 +1,4 @@
-use dioxus_core::{ElementId, Mutations, TemplateNode};
+use dioxus_core::{BorrowedAttributeValue, ElementId, Mutations, TemplateNode};
 use rustc_hash::{FxHashMap, FxHashSet};
 use std::fmt::Debug;
 use std::ops::{Deref, DerefMut, Index, IndexMut};
@@ -264,19 +264,32 @@ impl<S: State> RealDom<S> {
                     let node_id = self.element_to_node_id(id);
                     let node = self.tree.get_mut(node_id).unwrap();
                     if let NodeType::Element { attributes, .. } = &mut node.node_data.node_type {
-                        attributes.insert(
-                            OwnedAttributeDiscription {
+                        if let BorrowedAttributeValue::None = &value {
+                            attributes.remove(&OwnedAttributeDiscription {
                                 name: name.to_string(),
                                 namespace: ns.map(|s| s.to_string()),
                                 volatile: false,
-                            },
-                            OwnedAttributeValue::from(value),
-                        );
-                        mark_dirty(
-                            node_id,
-                            NodeMask::new_with_attrs(AttributeMask::single(name)),
-                            &mut nodes_updated,
-                        );
+                            });
+                            mark_dirty(
+                                node_id,
+                                NodeMask::new_with_attrs(AttributeMask::single(name)),
+                                &mut nodes_updated,
+                            );
+                        } else {
+                            attributes.insert(
+                                OwnedAttributeDiscription {
+                                    name: name.to_string(),
+                                    namespace: ns.map(|s| s.to_string()),
+                                    volatile: false,
+                                },
+                                OwnedAttributeValue::from(value),
+                            );
+                            mark_dirty(
+                                node_id,
+                                NodeMask::new_with_attrs(AttributeMask::single(name)),
+                                &mut nodes_updated,
+                            );
+                        }
                     }
                 }
                 SetText { value, id } => {