Bläddra i källkod

fix empty render causing panic (#1769) (#1774)

* fix empty render causing panic (#1769)

* use an default root column instead of an empty root column

* fix formatting

* restore create.rs in core

---------

Co-authored-by: Evan Almloff <evanalmloff@gmail.com>
abhi 1 år sedan
förälder
incheckning
fd7c9e0359
3 ändrade filer med 101 tillägg och 7 borttagningar
  1. 2 1
      packages/core/src/create.rs
  2. 11 6
      packages/rsx/src/lib.rs
  3. 88 0
      packages/ssr/src/renderer.rs

+ 2 - 1
packages/core/src/create.rs

@@ -205,7 +205,7 @@ impl<'b> VirtualDom {
         });
         });
     }
     }
 
 
-    /// We write all the descndent data for this element
+    /// We write all the descendent data for this element
     ///
     ///
     /// Elements can contain other nodes - and those nodes can be dynamic or static
     /// Elements can contain other nodes - and those nodes can be dynamic or static
     ///
     ///
@@ -405,6 +405,7 @@ impl<'b> VirtualDom {
     #[allow(unused_mut)]
     #[allow(unused_mut)]
     pub(crate) fn register_template(&mut self, mut template: Template<'static>) {
     pub(crate) fn register_template(&mut self, mut template: Template<'static>) {
         let (path, byte_index) = template.name.rsplit_once(':').unwrap();
         let (path, byte_index) = template.name.rsplit_once(':').unwrap();
+
         let byte_index = byte_index.parse::<usize>().unwrap();
         let byte_index = byte_index.parse::<usize>().unwrap();
         // First, check if we've already seen this template
         // First, check if we've already seen this template
         if self
         if self

+ 11 - 6
packages/rsx/src/lib.rs

@@ -204,12 +204,17 @@ impl<'a> ToTokens for TemplateRenderer<'a> {
             None => quote! { None },
             None => quote! { None },
         };
         };
 
 
-        let spndbg = format!("{:?}", self.roots[0].span());
-        let root_col = spndbg
-            .rsplit_once("..")
-            .and_then(|(_, after)| after.split_once(')').map(|(before, _)| before))
-            .unwrap_or_default();
-
+        let root_col = match self.roots.first() {
+            Some(first_root) => {
+                let first_root_span = format!("{:?}", first_root.span());
+                first_root_span
+                    .rsplit_once("..")
+                    .and_then(|(_, after)| after.split_once(')').map(|(before, _)| before))
+                    .unwrap_or_default()
+                    .to_string()
+            }
+            _ => "0".to_string(),
+        };
         let root_printer = self.roots.iter().enumerate().map(|(idx, root)| {
         let root_printer = self.roots.iter().enumerate().map(|(idx, root)| {
             context.current_path.push(idx as u8);
             context.current_path.push(idx as u8);
             let out = context.render_static_node(root);
             let out = context.render_static_node(root);

+ 88 - 0
packages/ssr/src/renderer.rs

@@ -238,6 +238,94 @@ fn to_string_works() {
     assert_eq!(out, "<div class=\"asdasdasd\" class=\"asdasdasd\" id=\"id-123\">Hello world 1 --&gt;123&lt;-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div>&lt;/diiiiiiiiv&gt;<div>finalize 0</div><div>finalize 1</div><div>finalize 2</div><div>finalize 3</div><div>finalize 4</div></div>");
     assert_eq!(out, "<div class=\"asdasdasd\" class=\"asdasdasd\" id=\"id-123\">Hello world 1 --&gt;123&lt;-- Hello world 2<div>nest 1</div><div></div><div>nest 2</div>&lt;/diiiiiiiiv&gt;<div>finalize 0</div><div>finalize 1</div><div>finalize 2</div><div>finalize 3</div><div>finalize 4</div></div>");
 }
 }
 
 
+#[test]
+fn empty_for_loop_works() {
+    use dioxus::prelude::*;
+
+    fn app(cx: Scope) -> Element {
+        render! {
+            div { class: "asdasdasd",
+                for _ in (0..5) {
+
+                }
+            }
+        }
+    }
+
+    let mut dom = VirtualDom::new(app);
+    _ = dom.rebuild();
+
+    let mut renderer = Renderer::new();
+    let out = renderer.render(&dom);
+
+    for item in renderer.template_cache.iter() {
+        if item.1.segments.len() > 5 {
+            assert_eq!(
+                item.1.segments,
+                vec![
+                    PreRendered("<div class=\"asdasdasd\"".into(),),
+                    Attr(0,),
+                    StyleMarker {
+                        inside_style_tag: false,
+                    },
+                    PreRendered(">".into()),
+                    InnerHtmlMarker,
+                    PreRendered("</div>".into(),),
+                ]
+            );
+        }
+    }
+
+    use Segment::*;
+
+    assert_eq!(out, "<div class=\"asdasdasd\"></div>");
+}
+
+#[test]
+fn empty_render_works() {
+    use dioxus::prelude::*;
+
+    fn app(cx: Scope) -> Element {
+        render! {}
+    }
+
+    let mut dom = VirtualDom::new(app);
+    _ = dom.rebuild();
+
+    let mut renderer = Renderer::new();
+    let out = renderer.render(&dom);
+
+    for item in renderer.template_cache.iter() {
+        if item.1.segments.len() > 5 {
+            assert_eq!(item.1.segments, vec![]);
+        }
+    }
+    assert_eq!(out, "");
+}
+
+#[test]
+fn empty_rsx_works() {
+    use dioxus::prelude::*;
+
+    fn app(_: Scope) -> Element {
+        rsx! {};
+        None
+    }
+
+    let mut dom = VirtualDom::new(app);
+    _ = dom.rebuild();
+
+    let mut renderer = Renderer::new();
+    let out = renderer.render(&dom);
+
+    for item in renderer.template_cache.iter() {
+        if item.1.segments.len() > 5 {
+            assert_eq!(item.1.segments, vec![]);
+        }
+    }
+    assert_eq!(out, "");
+}
+
 pub(crate) const BOOL_ATTRS: &[&str] = &[
 pub(crate) const BOOL_ATTRS: &[&str] = &[
     "allowfullscreen",
     "allowfullscreen",
     "allowpaymentrequest",
     "allowpaymentrequest",