Browse Source

fix serialization

Evan Almloff 2 years ago
parent
commit
96ce704f8e

+ 38 - 2
packages/core/src/nodes.rs

@@ -108,6 +108,10 @@ pub struct Template<'a> {
     /// The name of the template. This must be unique across your entire program for template diffing to work properly
     ///
     /// If two templates have the same name, it's likely that Dioxus will panic when diffing.
+    #[cfg_attr(
+        feature = "serialize",
+        serde(deserialize_with = "deserialize_string_leaky")
+    )]
     pub name: &'a str,
 
     /// The list of template nodes that make up the template
@@ -120,17 +124,49 @@ pub struct Template<'a> {
     ///
     /// These will be one segment shorter than the path sent to the renderer since those paths are relative to the
     /// topmost element, not the `roots` field.
-    #[cfg_attr(feature = "serialize", serde(deserialize_with = "deserialize_leaky"))]
+    #[cfg_attr(
+        feature = "serialize",
+        serde(deserialize_with = "deserialize_bytes_leaky")
+    )]
     pub node_paths: &'a [&'a [u8]],
 
     /// The paths of each dynamic attribute relative to the root of the template
     ///
     /// These will be one segment shorter than the path sent to the renderer since those paths are relative to the
     /// topmost element, not the `roots` field.
-    #[cfg_attr(feature = "serialize", serde(deserialize_with = "deserialize_leaky"))]
+    #[cfg_attr(
+        feature = "serialize",
+        serde(deserialize_with = "deserialize_bytes_leaky")
+    )]
     pub attr_paths: &'a [&'a [u8]],
 }
 
+#[cfg(feature = "serialize")]
+fn deserialize_string_leaky<'a, 'de, D>(deserializer: D) -> Result<&'a str, D::Error>
+where
+    D: serde::Deserializer<'de>,
+{
+    use serde::Deserialize;
+
+    let deserialized = String::deserialize(deserializer)?;
+    Ok(&*Box::leak(deserialized.into_boxed_str()))
+}
+
+#[cfg(feature = "serialize")]
+fn deserialize_bytes_leaky<'a, 'de, D>(deserializer: D) -> Result<&'a [&'a [u8]], D::Error>
+where
+    D: serde::Deserializer<'de>,
+{
+    use serde::Deserialize;
+
+    let deserialized = Vec::<Vec<u8>>::deserialize(deserializer)?;
+    let deserialized = deserialized
+        .into_iter()
+        .map(|v| &*Box::leak(v.into_boxed_slice()))
+        .collect::<Vec<_>>();
+    Ok(&*Box::leak(deserialized.into_boxed_slice()))
+}
+
 #[cfg(feature = "serialize")]
 fn deserialize_leaky<'a, 'de, T: serde::Deserialize<'de>, D>(
     deserializer: D,

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

@@ -458,6 +458,7 @@ impl VirtualDom {
     /// The caller must ensure that the template refrences the same dynamic attributes and nodes as the original template.
     pub fn replace_template(&mut self, template: Template<'static>) {
         self.templates.insert(template.name, template);
+        panic!("{:?}", self.templates);
         // iterating a slab is very inefficient, but this is a rare operation that will only happen during development so it's fine
         for (_, scope) in &self.scopes {
             if let Some(RenderReturn::Sync(Ok(sync))) = scope.try_root_node() {

+ 3 - 3
packages/rsx/src/lib.rs

@@ -19,7 +19,7 @@ mod hot_reloading_context;
 mod ifmt;
 mod node;
 
-use std::{collections::HashMap, hash::Hash};
+use std::{collections::HashMap, fmt::Debug, hash::Hash};
 
 // Re-export the namespaces into each other
 pub use component::*;
@@ -181,6 +181,7 @@ impl<'a, Ctx: HotReloadingContext> ToTokens for TemplateRenderer<'a, Ctx> {
         };
 
         let spndbg = format!("{:?}", self.roots[0].span());
+        println!("spndbg: {}", spndbg);
         let root_col = spndbg[9..].split("..").next().unwrap();
 
         let root_printer = self.roots.iter().enumerate().map(|(idx, root)| {
@@ -226,7 +227,7 @@ impl<'a, Ctx: HotReloadingContext> ToTokens for TemplateRenderer<'a, Ctx> {
     }
 }
 
-#[derive(Debug, Default)]
+#[derive(Default, Debug)]
 struct DynamicMapping {
     attribute_to_idx: HashMap<ElementAttr, Vec<usize>>,
     last_attribute_idx: usize,
@@ -240,7 +241,6 @@ impl DynamicMapping {
         for node in nodes {
             new.add_node(node);
         }
-        println!("{:#?}", new);
         new
     }
 

+ 6 - 2
packages/web/src/hot_reload.rs

@@ -20,6 +20,8 @@ pub(crate) fn init() -> UnboundedReceiver<Template<'static>> {
 pub(crate) fn init() -> UnboundedReceiver<Template<'static>> {
     use std::convert::TryInto;
 
+    use web_sys::console;
+
     let window = web_sys::window().unwrap();
 
     let protocol = if window.location().protocol().unwrap() == "https:" {
@@ -42,8 +44,10 @@ pub(crate) fn init() -> UnboundedReceiver<Template<'static>> {
         if let Ok(text) = e.data().dyn_into::<js_sys::JsString>() {
             let text: Result<String, _> = text.try_into();
             if let Ok(string) = text {
-                if let Ok(template) = serde_json::from_str(Box::leak(string.into_boxed_str())) {
-                    _ = tx.unbounded_send(template);
+                console::log_1(&string.clone().into());
+                match serde_json::from_str(Box::leak(string.into_boxed_str())) {
+                    Ok(template) => _ = tx.unbounded_send(template),
+                    Err(e) => console::log_1(&e.to_string().into()),
                 }
             }
         }

+ 2 - 0
packages/web/src/lib.rs

@@ -58,6 +58,7 @@ use crate::dom::virtual_event_from_websys_event;
 pub use crate::util::{use_eval, EvalResult};
 use dioxus_core::{Element, ElementId, Scope, VirtualDom};
 use futures_util::{pin_mut, FutureExt, StreamExt};
+use web_sys::console;
 
 mod cache;
 mod cfg;
@@ -209,6 +210,7 @@ pub async fn run_with_props<T: 'static>(root: fn(Scope<T>) -> Element, root_prop
             futures_util::select! {
                 _ = work => (None, None),
                 new_template = hotreload_rx.next() => {
+                    console::log_1(&"hot reload".into());
                     (None, new_template)
                 }
                 evt = rx.next() => (evt, None)