瀏覽代碼

wip: queue mods

Jonathan Kelley 2 年之前
父節點
當前提交
66319cf6e2
共有 4 個文件被更改,包括 76 次插入26 次删除
  1. 12 0
      examples/error_handle.rs
  2. 53 25
      packages/core/src/create.rs
  3. 4 1
      packages/core/src/mutations.rs
  4. 7 0
      packages/interpreter/src/interpreter.js

+ 12 - 0
examples/error_handle.rs

@@ -18,5 +18,17 @@ fn app(cx: Scope) -> Element {
             onclick: move |_| val.set("invalid"),
             "Set an invalid number"
         }
+        (0..5).map(|i| rsx! {
+            demo_c { x: i }
+        })
+    })
+}
+
+#[inline_props]
+fn demo_c(cx: Scope, x: i32) -> Element {
+    cx.render(rsx! {
+        h1 {
+            "asdasdasdasd {x}"
+        }
     })
 }

+ 53 - 25
packages/core/src/create.rs

@@ -45,37 +45,53 @@ impl VirtualDom {
 
         // Walk the roots, creating nodes and assigning IDs
         // todo: adjust dynamic nodes to be in the order of roots and then leaves (ie BFS)
-        let mut dynamic_attrs = template
-            .template
-            .attr_paths
-            .iter()
-            .enumerate()
-            .rev()
-            .peekable();
-        let mut dynamic_nodes = template
-            .template
-            .node_paths
-            .iter()
-            .enumerate()
-            .rev()
-            .peekable();
+        let mut dynamic_attrs = template.template.attr_paths.iter().enumerate().peekable();
+        let mut dynamic_nodes = template.template.node_paths.iter().enumerate().peekable();
 
         let cur_scope = self.scope_stack.last().copied().unwrap();
 
         println!("creating template: {:#?}", template);
 
         let mut on_stack = 0;
-        for (root_idx, root) in template.template.roots.iter().enumerate().rev() {
-            mutations.push(LoadTemplate {
-                name: template.template.id,
-                index: root_idx,
-            });
-
+        for (root_idx, root) in template.template.roots.iter().enumerate() {
             on_stack += match root {
-                TemplateNode::Element { .. } | TemplateNode::Text(_) => 1,
+                TemplateNode::Element { .. } | TemplateNode::Text(_) => {
+                    mutations.push(LoadTemplate {
+                        name: template.template.id,
+                        index: root_idx,
+                    });
+                    1
+                }
 
                 TemplateNode::DynamicText(id) | TemplateNode::Dynamic(id) => {
-                    self.create_dynamic_node(mutations, template, &template.dynamic_nodes[*id], *id)
+                    let dynamic_node = &template.dynamic_nodes[*id];
+
+                    match dynamic_node {
+                        DynamicNode::Fragment { .. } | DynamicNode::Component { .. } => self
+                            .create_dynamic_node(
+                                mutations,
+                                template,
+                                &template.dynamic_nodes[*id],
+                                *id,
+                            ),
+                        DynamicNode::Text {
+                            id: slot, value, ..
+                        } => {
+                            let id = self.next_element(template);
+                            slot.set(id);
+                            mutations.push(CreateTextNode {
+                                value: value.clone(),
+                                id,
+                            });
+                            1
+                        }
+                        DynamicNode::Placeholder(id) => {
+                            let id = self.next_element(template);
+                            mutations.push(CreatePlaceholder { id });
+                            1
+                        }
+                    }
+                    // self.create_dynamic_node(mutations, template, &template.dynamic_nodes[*id], *id)
                 }
             };
 
@@ -125,6 +141,14 @@ impl VirtualDom {
                 }
             }
 
+            // todo:
+            //
+            //  we walk the roots front to back when creating nodes, bur want to fill in the dynamic nodes
+            // back to front. This is because the indices would shift around because the paths become invalid
+            //
+            // We could easily implement this without the vec by walking the indicies forward
+            let mut queued_changes = vec![];
+
             // We're on top of a node that has a dynamic child for a descendant
             // Skip any node that's a root
             while let Some((idx, path)) =
@@ -133,12 +157,16 @@ impl VirtualDom {
                 let node = &template.dynamic_nodes[idx];
                 let m = self.create_dynamic_node(mutations, template, node, idx);
                 if m > 0 {
-                    mutations.push(ReplacePlaceholder {
+                    queued_changes.push(ReplacePlaceholder {
                         m,
                         path: &path[1..],
                     });
                 }
             }
+
+            for change in queued_changes.into_iter().rev() {
+                mutations.push(change);
+            }
         }
 
         on_stack
@@ -156,8 +184,8 @@ impl VirtualDom {
                 let id = self.next_element(template);
                 mutations.push(CreatePlaceholder { id })
             }
-            TemplateNode::Text(value) => mutations.push(CreateTextNode { value }),
-            TemplateNode::DynamicText { .. } => mutations.push(CreateTextNode {
+            TemplateNode::Text(value) => mutations.push(CreateStaticText { value }),
+            TemplateNode::DynamicText { .. } => mutations.push(CreateStaticText {
                 value: "placeholder",
             }),
 

+ 4 - 1
packages/core/src/mutations.rs

@@ -60,9 +60,12 @@ pub enum Mutation<'a> {
     CreatePlaceholder {
         id: ElementId,
     },
-
+    CreateStaticText {
+        value: &'a str,
+    },
     CreateTextNode {
         value: &'a str,
+        id: ElementId,
     },
     HydrateText {
         path: &'static [u8],

+ 7 - 0
packages/interpreter/src/interpreter.js

@@ -124,6 +124,10 @@ export class Interpreter {
       node.remove();
     }
   }
+  CreateRawText(text) {
+    const node = document.createTextNode(text);
+    this.stack.push(node);
+  }
   CreateTextNode(text, root) {
     const node = document.createTextNode(text);
     this.nodes[root] = node;
@@ -271,6 +275,9 @@ export class Interpreter {
       case "CreateTextNode":
         this.CreateTextNode(edit.value);
         break;
+      case "CreateStaticText":
+        this.CreateTextNode(edit.value);
+        break;
       case "HydrateText":
         this.HydrateText(edit.path, edit.value, edit.id);
         break;