feat: none return works

This commit is contained in:
Jonathan Kelley 2022-12-23 19:33:15 -05:00
parent 244ade048e
commit d8aa9f032a
3 changed files with 37 additions and 30 deletions

View file

@ -272,9 +272,9 @@ impl<'b> VirtualDom {
use DynamicNode::*;
match node {
Text(text) => self.create_dynamic_text(template, text, idx),
Fragment(frag) => self.create_fragment(frag),
Placeholder(frag) => self.create_placeholder(frag, template, idx),
Component(component) => self.create_component_node(template, component, idx),
Fragment(frag) => frag.iter().map(|child| self.create(child)).sum(),
}
}
@ -326,43 +326,44 @@ impl<'b> VirtualDom {
0
}
pub(crate) fn create_fragment(&mut self, nodes: &'b [VNode<'b>]) -> usize {
nodes.iter().map(|child| self.create(child)).sum()
}
pub(super) fn create_component_node(
&mut self,
template: &'b VNode<'b>,
component: &'b VComponent<'b>,
idx: usize,
) -> usize {
let scope = match component.props.take() {
Some(props) => {
let unbounded_props: Box<dyn AnyProps> = unsafe { std::mem::transmute(props) };
let scope = self.new_scope(unbounded_props, component.name);
scope.id
}
// Component is coming back, it probably still exists, right?
None => component.scope.get().unwrap(),
};
component.scope.set(Some(scope));
let return_nodes = unsafe { self.run_scope(scope).extend_lifetime_ref() };
use RenderReturn::*;
match return_nodes {
// Load up a ScopeId for this vcomponent
let scope = self.load_scope_from_vcomponent(component);
match unsafe { self.run_scope(scope).extend_lifetime_ref() } {
Ready(t) => self.mount_component(scope, template, t, idx),
Aborted(t) => {
self.mutations
.push(Mutation::CreatePlaceholder { id: ElementId(999) });
Aborted(t) => self.mount_aborted(template, t),
Async(_) => self.mount_component_placeholder(template, idx, scope),
}
}
fn mount_aborted(&mut self, parent: &'b VNode<'b>, placeholder: &VPlaceholder) -> usize {
let id = self.next_element(parent, &[]);
self.mutations.push(Mutation::CreatePlaceholder { id });
placeholder.id.set(Some(id));
1
}
Async(_) => self.mount_component_placeholder(template, idx, scope),
}
/// Load a scope from a vcomponent. If the props don't exist, that means the component is currently "live"
fn load_scope_from_vcomponent(&mut self, component: &VComponent) -> ScopeId {
component
.props
.take()
.map(|props| {
let unbounded_props: Box<dyn AnyProps> = unsafe { std::mem::transmute(props) };
self.new_scope(unbounded_props, component.name).id
})
.unwrap_or_else(|| component.scope.get().unwrap())
}
fn mount_component(

View file

@ -27,8 +27,6 @@ pub enum RenderReturn<'a> {
///
/// In its place we've produced a placeholder to locate its spot in the dom when
/// it recovers.
///
/// The old nodes are kept around
Aborted(VPlaceholder),
/// An ongoing future that will resolve to a [`Element`]

View file

@ -6,16 +6,24 @@ fn catches_panic() {
let mut dom = VirtualDom::new(app);
let a = dom.rebuild();
dbg!(a);
}
fn app(cx: Scope) -> Element {
cx.render(rsx! {
div {
PanicChild {}
h1 { "Title" }
NoneChild {}
}
})
}
fn NoneChild(cx: Scope) -> Element {
None
}
fn PanicChild(cx: Scope) -> Element {
panic!("Rendering panicked for whatever reason");