Fix mount use after removal/Simplify mounts a bit (#2834)
* remove clone mounted; mounted nodes should never leak into components? * Remove the mount from vnodes after unmounting them * Fix use after removal in iterator diffing * remove logs * Re-fix keyed list diffing * Use new.len for diffing keyed lens and remove redundant check * simplify core list diffing logic a bit * remove println * add proper asserts for new tests --------- Co-authored-by: Jonathan Kelley <jkelleyrtp@gmail.com>
This commit is contained in:
1 parent
959ab67624
commit
d649b0c54d
13 files changed
+310
-221
No files matched your search
+38
-87
@@ -1,4 +1,5 @@
|
||||
use crate::innerlude::{RenderError, VProps};
|
||||
use crate::innerlude::VProps;
|
||||
use crate::prelude::RenderError;
|
||||
use crate::{any_props::BoxedAnyProps, innerlude::ScopeState};
|
||||
use crate::{arena::ElementId, Element, Event};
|
||||
use crate::{
|
||||
@@ -6,7 +7,7 @@ use crate::{
|
||||
properties::ComponentFunction,
|
||||
};
|
||||
use crate::{Properties, ScopeId, VirtualDom};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use std::vec;
|
||||
use std::{
|
||||
@@ -15,77 +16,6 @@ use std::{
|
||||
fmt::{Arguments, Debug},
|
||||
};
|
||||
|
||||
/// The actual state of the component's most recent computation
|
||||
///
|
||||
/// If the component returned early (e.g. `return None`), this will be Aborted(None)
|
||||
#[derive(Debug)]
|
||||
pub struct RenderReturn {
|
||||
/// The node that was rendered
|
||||
pub(crate) node: Element,
|
||||
}
|
||||
|
||||
impl From<RenderReturn> for VNode {
|
||||
fn from(val: RenderReturn) -> Self {
|
||||
match val.node {
|
||||
Ok(node) => node,
|
||||
Err(RenderError::Aborted(e)) => e.render,
|
||||
Err(RenderError::Suspended(fut)) => fut.placeholder,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Element> for RenderReturn {
|
||||
fn from(node: Element) -> Self {
|
||||
RenderReturn { node }
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for RenderReturn {
|
||||
fn clone(&self) -> Self {
|
||||
match &self.node {
|
||||
Ok(node) => RenderReturn {
|
||||
node: Ok(node.clone_mounted()),
|
||||
},
|
||||
Err(RenderError::Aborted(err)) => RenderReturn {
|
||||
node: Err(RenderError::Aborted(err.clone_mounted())),
|
||||
},
|
||||
Err(RenderError::Suspended(fut)) => RenderReturn {
|
||||
node: Err(RenderError::Suspended(fut.clone_mounted())),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RenderReturn {
|
||||
fn default() -> Self {
|
||||
RenderReturn {
|
||||
node: Ok(VNode::placeholder()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for RenderReturn {
|
||||
type Target = VNode;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match &self.node {
|
||||
Ok(node) => node,
|
||||
Err(RenderError::Aborted(err)) => &err.render,
|
||||
Err(RenderError::Suspended(fut)) => &fut.placeholder,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for RenderReturn {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
match &mut self.node {
|
||||
Ok(node) => node,
|
||||
Err(RenderError::Aborted(err)) => &mut err.render,
|
||||
Err(RenderError::Suspended(fut)) => &mut fut.placeholder,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The information about the
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct VNodeMount {
|
||||
@@ -162,7 +92,7 @@ pub struct VNodeInner {
|
||||
///
|
||||
/// The dynamic parts of the template are stored separately from the static parts. This allows faster diffing by skipping
|
||||
/// static parts of the template.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VNode {
|
||||
vnode: Rc<VNodeInner>,
|
||||
|
||||
@@ -170,15 +100,44 @@ pub struct VNode {
|
||||
pub(crate) mount: Cell<MountId>,
|
||||
}
|
||||
|
||||
impl Clone for VNode {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
vnode: self.vnode.clone(),
|
||||
mount: Default::default(),
|
||||
impl AsRef<VNode> for Element {
|
||||
fn as_ref(&self) -> &VNode {
|
||||
match self {
|
||||
Element::Ok(node) => node,
|
||||
Element::Err(RenderError::Aborted(err)) => &err.render,
|
||||
Element::Err(RenderError::Suspended(fut)) => &fut.placeholder,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Element> for VNode {
|
||||
fn from(val: &Element) -> Self {
|
||||
AsRef::as_ref(val).clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Element> for VNode {
|
||||
fn from(val: Element) -> Self {
|
||||
match val {
|
||||
Element::Ok(node) => node,
|
||||
Element::Err(RenderError::Aborted(err)) => err.render,
|
||||
Element::Err(RenderError::Suspended(fut)) => fut.placeholder,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A tiny helper trait to get the vnode for a Element
|
||||
pub(crate) trait AsVNode {
|
||||
/// Get the vnode for this element
|
||||
fn as_vnode(&self) -> &VNode;
|
||||
}
|
||||
|
||||
impl AsVNode for Element {
|
||||
fn as_vnode(&self) -> &VNode {
|
||||
AsRef::as_ref(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for VNode {
|
||||
fn default() -> Self {
|
||||
Self::placeholder()
|
||||
@@ -223,14 +182,6 @@ impl Deref for VNode {
|
||||
}
|
||||
|
||||
impl VNode {
|
||||
/// Clone the element while retaining the mount information of the node
|
||||
pub(crate) fn clone_mounted(&self) -> Self {
|
||||
Self {
|
||||
vnode: self.vnode.clone(),
|
||||
mount: self.mount.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a template with no nodes that will be skipped over during diffing
|
||||
pub fn empty() -> Element {
|
||||
Ok(Self::default())
|
||||
|
||||
Reference in new issue
Block a user