diff --git a/packages/core/src/arena.rs b/packages/core/src/arena.rs index b89afb4cd..9909e2fb4 100644 --- a/packages/core/src/arena.rs +++ b/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. diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index 0dcf07fff..fa11a6e2f 100644 --- a/packages/core/src/diff.rs +++ b/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 { diff --git a/packages/liveview/src/main.js b/packages/liveview/src/main.js index e37ac7b67..bdf656b50 100644 --- a/packages/liveview/src/main.js +++ b/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) {