فهرست منبع

Merge branch 'upstream' into fix-hot-reloading

Evan Almloff 2 سال پیش
والد
کامیت
608c37428d
3فایلهای تغییر یافته به همراه37 افزوده شده و 34 حذف شده
  1. 8 5
      packages/core/src/arena.rs
  2. 21 19
      packages/core/src/diff.rs
  3. 8 10
      packages/liveview/src/main.js

+ 8 - 5
packages/core/src/arena.rs

@@ -134,8 +134,8 @@ impl VirtualDom {
     }
 
     /// Descend through the tree, removing any borrowed props and listeners
-    pub(crate) fn ensure_drop_safety(&self, scope: ScopeId) {
-        let scope = &self.scopes[scope.0];
+    pub(crate) fn ensure_drop_safety(&self, scope_id: ScopeId) {
+        let scope = &self.scopes[scope_id.0];
 
         // make sure we drop all borrowed props manually to guarantee that their drop implementation is called before we
         // run the hooks (which hold an &mut Reference)
@@ -143,10 +143,13 @@ impl VirtualDom {
         let mut props = scope.borrowed_props.borrow_mut();
         props.drain(..).for_each(|comp| {
             let comp = unsafe { &*comp };
-            if let Some(scope_id) = comp.scope.get() {
-                self.ensure_drop_safety(scope_id);
+            match comp.scope.get() {
+                Some(child) if child != scope_id => self.ensure_drop_safety(child),
+                _ => (),
+            }
+            if let Ok(mut props) = comp.props.try_borrow_mut() {
+                *props = None;
             }
-            drop(comp.props.take());
         });
 
         // Now that all the references are gone, we can safely drop our own references in our listeners.

+ 21 - 19
packages/core/src/diff.rs

@@ -840,10 +840,9 @@ impl<'b> VirtualDom {
                 .node_paths
                 .get(idx)
                 .map(|path| path.len());
-            match path_len {
-                Some(2..) => self.remove_dynamic_node(dyn_node, false),
-                // Roots are cleaned up automatically above and nodes with a empty path are placeholders
-                _ => continue,
+            // Roots are cleaned up automatically above and nodes with a empty path are placeholders
+            if let Some(2..) = path_len {
+                self.remove_dynamic_node(dyn_node, false)
             }
         }
     }
@@ -878,25 +877,28 @@ impl<'b> VirtualDom {
     }
 
     fn remove_component_node(&mut self, comp: &VComponent, gen_muts: bool) {
-        if let Some(scope) = comp.scope.take() {
-            match unsafe { self.scopes[scope.0].root_node().extend_lifetime_ref() } {
-                RenderReturn::Sync(Some(t)) => self.remove_node(t, gen_muts),
-                _ => todo!("cannot handle nonstandard nodes"),
-            };
+        let scope = comp.scope.take().unwrap();
 
-            let props = self.scopes[scope.0].props.take();
+        match unsafe { self.scopes[scope.0].root_node().extend_lifetime_ref() } {
+            RenderReturn::Sync(Some(t)) => {
+                println!("Removing component node sync {:?}", gen_muts);
+                self.remove_node(t, gen_muts)
+            }
+            _ => todo!("cannot handle nonstandard nodes"),
+        };
 
-            self.dirty_scopes.remove(&DirtyScope {
-                height: self.scopes[scope.0].height,
-                id: scope,
-            });
+        let props = self.scopes[scope.0].props.take();
 
-            *comp.props.borrow_mut() = unsafe { std::mem::transmute(props) };
+        self.dirty_scopes.remove(&DirtyScope {
+            height: self.scopes[scope.0].height,
+            id: scope,
+        });
 
-            // make sure to wipe any of its props and listeners
-            self.ensure_drop_safety(scope);
-            self.scopes.remove(scope.0);
-        }
+        *comp.props.borrow_mut() = unsafe { std::mem::transmute(props) };
+
+        // make sure to wipe any of its props and listeners
+        self.ensure_drop_safety(scope);
+        self.scopes.remove(scope.0);
     }
 
     fn find_first_element(&self, node: &'b VNode<'b>) -> ElementId {

+ 8 - 10
packages/liveview/src/main.js

@@ -1,10 +1,7 @@
 function main() {
   let root = window.document.getElementById("main");
-
   if (root != null) {
-    // create a new ipc
     window.ipc = new IPC(root);
-    window.ipc.postMessage(serializeIpcMessage("initialize"));
   }
 }
 
@@ -13,21 +10,22 @@ class IPC {
     // connect to the websocket
     window.interpreter = new Interpreter(root);
 
-    this.ws = new WebSocket(WS_ADDR);
+    let ws = new WebSocket(WS_ADDR);
 
-    this.ws.onopen = () => {
-      console.log("Connected to the websocket");
+    ws.onopen = () => {
+      ws.send(serializeIpcMessage("initialize"));
     };
 
-    this.ws.onerror = (err) => {
-      console.error("Error: ", err);
+    ws.onerror = (err) => {
+      // todo: retry the connection
     };
 
-    this.ws.onmessage = (event) => {
-      console.log("Received message: ", event.data);
+    ws.onmessage = (event) => {
       let edits = JSON.parse(event.data);
       window.interpreter.handleEdits(edits);
     };
+
+    this.ws = ws;
   }
 
   postMessage(msg) {