chore: wipe away old src
This commit is contained in:
1 parent
493591400f
commit
d407035931
29 files changed
+187
-6819
No files matched your search
@@ -7,20 +7,33 @@ use crate::{
|
||||
Element,
|
||||
};
|
||||
|
||||
pub trait AnyProps<'a> {
|
||||
fn as_ptr(&self) -> *const ();
|
||||
/// A trait that essentially allows VComponentProps to be used generically
|
||||
pub unsafe trait AnyProps<'a> {
|
||||
fn props_ptr(&self) -> *const ();
|
||||
fn render(&'a self, bump: &'a ScopeState) -> RenderReturn<'a>;
|
||||
unsafe fn memoize(&self, other: &dyn AnyProps) -> bool;
|
||||
}
|
||||
|
||||
pub(crate) struct VComponentProps<'a, P, A, F: ComponentReturn<'a, A> = Element<'a>> {
|
||||
pub(crate) struct VProps<'a, P, A, F: ComponentReturn<'a, A> = Element<'a>> {
|
||||
pub render_fn: fn(Scope<'a, P>) -> F,
|
||||
pub memo: unsafe fn(&P, &P) -> bool,
|
||||
pub props: P,
|
||||
pub _marker: PhantomData<A>,
|
||||
// pub props: PropsAllocation<P>,
|
||||
_marker: PhantomData<A>,
|
||||
}
|
||||
|
||||
impl<'a, P, A, F: ComponentReturn<'a, A>> VComponentProps<'a, P, A, F> {
|
||||
enum PropsAllocation<P> {
|
||||
/// If it's memoized, then the heap owns the props
|
||||
Memoized(*mut P),
|
||||
|
||||
/// If it's borrowed, then the parent owns the props
|
||||
Borrowed(P),
|
||||
}
|
||||
|
||||
impl<'a, P, A, F> VProps<'a, P, A, F>
|
||||
where
|
||||
F: ComponentReturn<'a, A>,
|
||||
{
|
||||
pub(crate) fn new(
|
||||
render_fn: fn(Scope<'a, P>) -> F,
|
||||
memo: unsafe fn(&P, &P) -> bool,
|
||||
@@ -30,13 +43,17 @@ impl<'a, P, A, F: ComponentReturn<'a, A>> VComponentProps<'a, P, A, F> {
|
||||
render_fn,
|
||||
memo,
|
||||
props,
|
||||
// props: PropsAllocation::Borrowed(props),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, P, A, F: ComponentReturn<'a, A>> AnyProps<'a> for VComponentProps<'a, P, A, F> {
|
||||
fn as_ptr(&self) -> *const () {
|
||||
unsafe impl<'a, P, A, F> AnyProps<'a> for VProps<'a, P, A, F>
|
||||
where
|
||||
F: ComponentReturn<'a, A>,
|
||||
{
|
||||
fn props_ptr(&self) -> *const () {
|
||||
&self.props as *const _ as *const ()
|
||||
}
|
||||
|
||||
@@ -45,8 +62,8 @@ impl<'a, P, A, F: ComponentReturn<'a, A>> AnyProps<'a> for VComponentProps<'a, P
|
||||
// you *must* make this check *before* calling this method
|
||||
// if your functions are not the same, then you will downcast a pointer into a different type (UB)
|
||||
unsafe fn memoize(&self, other: &dyn AnyProps) -> bool {
|
||||
let real_other: &P = &*(other.as_ptr() as *const _ as *const P);
|
||||
let real_us: &P = &*(self.as_ptr() as *const _ as *const P);
|
||||
let real_other: &P = &*(other.props_ptr() as *const _ as *const P);
|
||||
let real_us: &P = &*(self.props_ptr() as *const _ as *const P);
|
||||
(self.memo)(real_us, real_other)
|
||||
}
|
||||
|
||||
|
||||
@@ -70,11 +70,7 @@ impl VirtualDom {
|
||||
&template.dynamic_nodes[*id],
|
||||
*id,
|
||||
),
|
||||
DynamicNode::Text(VText {
|
||||
id: slot,
|
||||
value,
|
||||
inner,
|
||||
}) => {
|
||||
DynamicNode::Text(VText { id: slot, value }) => {
|
||||
let id = self.next_element(template, template.template.node_paths[*id]);
|
||||
slot.set(id);
|
||||
mutations.push(CreateTextNode { value, id });
|
||||
@@ -239,7 +235,7 @@ impl VirtualDom {
|
||||
idx: usize,
|
||||
) -> usize {
|
||||
match &node {
|
||||
DynamicNode::Text(VText { id, value, inner }) => {
|
||||
DynamicNode::Text(VText { id, value }) => {
|
||||
let new_id = self.next_element(template, template.template.node_paths[idx]);
|
||||
id.set(new_id);
|
||||
mutations.push(HydrateText {
|
||||
@@ -251,9 +247,10 @@ impl VirtualDom {
|
||||
}
|
||||
|
||||
DynamicNode::Component(component) => {
|
||||
let scope = self
|
||||
.new_scope(unsafe { std::mem::transmute(component.props.get()) })
|
||||
.id;
|
||||
let props = component.props.replace(None).unwrap();
|
||||
let prop_ptr = unsafe { std::mem::transmute(props.as_ref()) };
|
||||
let scope = self.new_scope(prop_ptr).id;
|
||||
component.props.replace(Some(props));
|
||||
|
||||
component.scope.set(Some(scope));
|
||||
|
||||
|
||||
+123
-83
@@ -5,7 +5,8 @@ use crate::innerlude::{Mutations, VComponent, VFragment, VText};
|
||||
use crate::virtual_dom::VirtualDom;
|
||||
use crate::{Attribute, AttributeValue, TemplateNode};
|
||||
|
||||
use crate::any_props::VComponentProps;
|
||||
use crate::any_props::VProps;
|
||||
use DynamicNode::*;
|
||||
|
||||
use crate::mutations::Mutation;
|
||||
use crate::nodes::{DynamicNode, Template, TemplateId};
|
||||
@@ -77,7 +78,7 @@ impl<'b> VirtualDom {
|
||||
use RenderReturn::{Async, Sync};
|
||||
match (left, right) {
|
||||
// diff
|
||||
(Sync(Some(l)), Sync(Some(r))) => self.diff_node(m, l, r),
|
||||
(Sync(Some(l)), Sync(Some(r))) => self.diff_vnode(m, l, r),
|
||||
|
||||
// remove old with placeholder
|
||||
(Sync(Some(l)), Sync(None)) | (Sync(Some(l)), Async(_)) => {
|
||||
@@ -91,7 +92,7 @@ impl<'b> VirtualDom {
|
||||
(Sync(None), Sync(Some(_))) => {}
|
||||
(Async(_), Sync(Some(v))) => {}
|
||||
|
||||
// nothing...
|
||||
// nothing... just transfer the placeholders over
|
||||
(Async(_), Async(_))
|
||||
| (Sync(None), Sync(None))
|
||||
| (Sync(None), Async(_))
|
||||
@@ -99,23 +100,20 @@ impl<'b> VirtualDom {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn diff_node(
|
||||
pub fn diff_vnode(
|
||||
&mut self,
|
||||
muts: &mut Mutations<'b>,
|
||||
left_template: &'b VNode<'b>,
|
||||
right_template: &'b VNode<'b>,
|
||||
) {
|
||||
if left_template.template.id != right_template.template.id {
|
||||
// do a light diff of the roots nodes.
|
||||
todo!("lightly diff roots and replace");
|
||||
return;
|
||||
return self.light_diff_templates(muts, left_template, right_template);
|
||||
}
|
||||
|
||||
for (_idx, (left_attr, right_attr)) in left_template
|
||||
for (left_attr, right_attr) in left_template
|
||||
.dynamic_attrs
|
||||
.iter()
|
||||
.zip(right_template.dynamic_attrs.iter())
|
||||
.enumerate()
|
||||
{
|
||||
// Move over the ID from the old to the new
|
||||
right_attr
|
||||
@@ -135,67 +133,76 @@ impl<'b> VirtualDom {
|
||||
}
|
||||
}
|
||||
|
||||
for (idx, (left_node, right_node)) in left_template
|
||||
for (left_node, right_node) in left_template
|
||||
.dynamic_nodes
|
||||
.iter()
|
||||
.zip(right_template.dynamic_nodes.iter())
|
||||
.enumerate()
|
||||
{
|
||||
use DynamicNode::*;
|
||||
|
||||
match (left_node, right_node) {
|
||||
(Component(left), Component(right)) => self.diff_vcomponent(muts, left, right),
|
||||
(Text(left), Text(right)) => self.diff_vtext(muts, left, right),
|
||||
(Fragment(left), Fragment(right)) => self.diff_vfragment(muts, left, right),
|
||||
|
||||
(Placeholder(_), Placeholder(_)) => todo!(),
|
||||
|
||||
// Make sure to drop all the fragment children properly
|
||||
(DynamicNode::Fragment { .. }, right) => todo!(),
|
||||
|
||||
(Text(left), right) => {
|
||||
todo!()
|
||||
// let m = self.create_dynamic_node(muts, right_template, right, idx);
|
||||
// muts.push(Mutation::ReplaceWith { id: lid.get(), m });
|
||||
}
|
||||
(Placeholder(_), _) => todo!(),
|
||||
// Make sure to drop the component properly
|
||||
(Component { .. }, right) => {
|
||||
// remove all the component roots except for the first
|
||||
// replace the first with the new node
|
||||
let m = self.create_dynamic_node(muts, right_template, right, idx);
|
||||
todo!()
|
||||
}
|
||||
(Placeholder(left), Placeholder(right)) => right.set(left.get()),
|
||||
_ => self.replace(muts, left_template, right_template, left_node, right_node),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn replace(
|
||||
&mut self,
|
||||
muts: &mut Mutations<'b>,
|
||||
left_template: &'b VNode<'b>,
|
||||
right_template: &'b VNode<'b>,
|
||||
left: &'b DynamicNode<'b>,
|
||||
right: &'b DynamicNode<'b>,
|
||||
) {
|
||||
}
|
||||
|
||||
fn diff_vcomponent(
|
||||
&mut self,
|
||||
muts: &mut Mutations<'b>,
|
||||
left: &'b VComponent<'b>,
|
||||
right: &'b VComponent<'b>,
|
||||
) {
|
||||
let left_props = unsafe { &mut *left.props.get() };
|
||||
let right_props = unsafe { &mut *right.props.get() };
|
||||
// Due to how templates work, we should never get two different components. The only way we could enter
|
||||
// this codepath is through "light_diff", but we check there that the pointers are the same
|
||||
assert_eq!(left.render_fn, right.render_fn);
|
||||
|
||||
// Ensure these two props are of the same component type
|
||||
match left_props.as_ptr() == right_props.as_ptr() {
|
||||
true => {
|
||||
//
|
||||
if left.static_props {
|
||||
let props_are_same = unsafe { left_props.memoize(right_props) };
|
||||
/*
|
||||
|
||||
if props_are_same {
|
||||
//
|
||||
} else {
|
||||
//
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
false => todo!(),
|
||||
|
||||
|
||||
let left = rsx!{ Component {} }
|
||||
let right = rsx!{ Component {} }
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
// Make sure the new vcomponent has the right scopeid associated to it
|
||||
let scope_id = left.scope.get().unwrap();
|
||||
right.scope.set(Some(scope_id));
|
||||
|
||||
// copy out the box for both
|
||||
let old = left.props.replace(None).unwrap();
|
||||
let new = right.props.replace(None).unwrap();
|
||||
|
||||
// If the props are static, then we try to memoize by setting the new with the old
|
||||
// The target scopestate still has the reference to the old props, so there's no need to update anything
|
||||
// This also implicitly drops the new props since they're not used
|
||||
if left.static_props && unsafe { old.memoize(new.as_ref()) } {
|
||||
return right.props.set(Some(old));
|
||||
}
|
||||
|
||||
// If the props are dynamic *or* the memoization failed, then we need to diff the props
|
||||
|
||||
// First, move over the props from the old to the new, dropping old props in the process
|
||||
self.scopes[scope_id.0].props = unsafe { std::mem::transmute(new.as_ref()) };
|
||||
right.props.set(Some(new));
|
||||
|
||||
// Now run the component and diff it
|
||||
self.run_scope(scope_id);
|
||||
self.diff_scope(muts, scope_id);
|
||||
}
|
||||
|
||||
/// Lightly diff the two templates, checking only their roots.
|
||||
@@ -236,44 +243,23 @@ impl<'b> VirtualDom {
|
||||
/// Component { ..props }
|
||||
/// }
|
||||
/// ```
|
||||
fn light_diff_tempaltes(
|
||||
fn light_diff_templates(
|
||||
&mut self,
|
||||
muts: &mut Mutations<'b>,
|
||||
left: &'b VNode<'b>,
|
||||
right: &'b VNode<'b>,
|
||||
) -> bool {
|
||||
if left.template.roots.len() != right.template.roots.len() {
|
||||
return false;
|
||||
) {
|
||||
if let Some(components) = matching_components(left, right) {
|
||||
components
|
||||
.into_iter()
|
||||
.for_each(|(l, r)| self.diff_vcomponent(muts, l, r))
|
||||
}
|
||||
|
||||
let mut components = vec![];
|
||||
|
||||
// run through the components, ensuring they're the same
|
||||
for (l, r) in left.template.roots.iter().zip(right.template.roots.iter()) {
|
||||
match (l, r) {
|
||||
(TemplateNode::Dynamic(l), TemplateNode::Dynamic(r)) => {
|
||||
components.push(match (&left.dynamic_nodes[*l], &right.dynamic_nodes[*r]) {
|
||||
(DynamicNode::Component(l), DynamicNode::Component(r)) => {
|
||||
let l_props = unsafe { &*l.props.get() };
|
||||
let r_props = unsafe { &*r.props.get() };
|
||||
|
||||
(l, r)
|
||||
}
|
||||
_ => return false,
|
||||
})
|
||||
}
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
|
||||
// run through the components, diffing them
|
||||
for (l, r) in components {
|
||||
self.diff_vcomponent(muts, l, r);
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
/// Diff the two text nodes
|
||||
///
|
||||
/// This just moves the ID of the old node over to the new node, and then sets the text of the new node if it's
|
||||
/// different.
|
||||
fn diff_vtext(&mut self, muts: &mut Mutations<'b>, left: &'b VText<'b>, right: &'b VText<'b>) {
|
||||
right.id.set(left.id.get());
|
||||
if left.value != right.value {
|
||||
@@ -297,6 +283,7 @@ impl<'b> VirtualDom {
|
||||
// todo!()
|
||||
// }
|
||||
// (_, []) => {
|
||||
// // if this fragment is the only child of its parent, then we can use the "RemoveAllChildren" mutation
|
||||
// todo!()
|
||||
// }
|
||||
// _ => {
|
||||
@@ -319,8 +306,6 @@ impl<'b> VirtualDom {
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
todo!()
|
||||
}
|
||||
|
||||
// Diff children that are not keyed.
|
||||
@@ -351,7 +336,7 @@ impl<'b> VirtualDom {
|
||||
}
|
||||
|
||||
for (new, old) in new.iter().zip(old.iter()) {
|
||||
self.diff_node(muts, old, new);
|
||||
self.diff_vnode(muts, old, new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -693,3 +678,58 @@ impl<'b> VirtualDom {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
fn matching_components<'a>(
|
||||
left: &'a VNode<'a>,
|
||||
right: &'a VNode<'a>,
|
||||
) -> Option<Vec<(&'a VComponent<'a>, &'a VComponent<'a>)>> {
|
||||
if left.template.roots.len() != right.template.roots.len() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// run through the components, ensuring they're the same
|
||||
left.template
|
||||
.roots
|
||||
.iter()
|
||||
.zip(right.template.roots.iter())
|
||||
.map(|(l, r)| {
|
||||
let (l, r) = match (l, r) {
|
||||
(TemplateNode::Dynamic(l), TemplateNode::Dynamic(r)) => (l, r),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let (l, r) = match (&left.dynamic_nodes[*l], &right.dynamic_nodes[*r]) {
|
||||
(Component(l), Component(r)) => (l, r),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
(l.render_fn == r.render_fn).then(|| (l, r))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// We can apply various optimizations to dynamic nodes that are the single child of their parent.
|
||||
///
|
||||
/// IE
|
||||
/// - for text - we can use SetTextContent
|
||||
/// - for clearning children we can use RemoveChildren
|
||||
/// - for appending children we can use AppendChildren
|
||||
fn is_dyn_node_only_child(node: &VNode, idx: usize) -> bool {
|
||||
let path = node.template.node_paths[idx];
|
||||
|
||||
// use a loop to index every static node's children until the path has run out
|
||||
// only break if the last path index is a dynamic node
|
||||
let mut static_node = &node.template.roots[path[0] as usize];
|
||||
|
||||
for i in 1..path.len() - 1 {
|
||||
match static_node {
|
||||
TemplateNode::Element { children, .. } => static_node = &children[path[i] as usize],
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
|
||||
match static_node {
|
||||
TemplateNode::Element { children, .. } => children.len() == 1,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
use std::{
|
||||
any::Any,
|
||||
cell::{Cell, RefCell},
|
||||
fmt::Arguments,
|
||||
};
|
||||
@@ -8,7 +9,7 @@ use bumpalo::Bump;
|
||||
use std::future::Future;
|
||||
|
||||
use crate::{
|
||||
any_props::{AnyProps, VComponentProps},
|
||||
any_props::{AnyProps, VProps},
|
||||
arena::ElementId,
|
||||
innerlude::{DynamicNode, EventHandler, VComponent, VFragment, VText},
|
||||
Attribute, AttributeValue, Element, LazyNodes, Properties, Scope, ScopeState, VNode,
|
||||
@@ -21,7 +22,6 @@ impl ScopeState {
|
||||
DynamicNode::Text(VText {
|
||||
id: Cell::new(ElementId(0)),
|
||||
value: text,
|
||||
inner: false,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -76,10 +76,11 @@ impl ScopeState {
|
||||
P: Properties + 'a,
|
||||
{
|
||||
let as_component = component;
|
||||
let vcomp = VComponentProps::new(as_component, P::memoize, props);
|
||||
let as_dyn = self.bump().alloc(vcomp) as &mut dyn AnyProps;
|
||||
let detached_dyn: *mut dyn AnyProps = unsafe { std::mem::transmute(as_dyn) };
|
||||
let vcomp = VProps::new(as_component, P::memoize, props);
|
||||
let as_dyn: Box<dyn AnyProps<'a>> = Box::new(vcomp);
|
||||
let extended: Box<dyn AnyProps> = unsafe { std::mem::transmute(as_dyn) };
|
||||
|
||||
// let as_dyn: &dyn AnyProps = self.bump().alloc(vcomp);
|
||||
// todo: clean up borrowed props
|
||||
// if !P::IS_STATIC {
|
||||
// let vcomp = &*vcomp;
|
||||
@@ -89,8 +90,9 @@ impl ScopeState {
|
||||
|
||||
DynamicNode::Component(VComponent {
|
||||
name: fn_name,
|
||||
render_fn: component as *const (),
|
||||
static_props: P::IS_STATIC,
|
||||
props: Cell::new(detached_dyn),
|
||||
props: Cell::new(Some(extended)),
|
||||
placeholder: Cell::new(None),
|
||||
scope: Cell::new(None),
|
||||
})
|
||||
@@ -178,7 +180,6 @@ impl<'a, 'b> IntoDynNode<'a> for LazyNodes<'a, 'b> {
|
||||
fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a> {
|
||||
DynamicNode::Fragment(VFragment {
|
||||
nodes: cx.bump().alloc([self.call(cx)]),
|
||||
inner: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -248,10 +249,7 @@ where
|
||||
|
||||
match children.len() {
|
||||
0 => DynamicNode::Placeholder(Cell::new(ElementId(0))),
|
||||
_ => DynamicNode::Fragment(VFragment {
|
||||
inner: false,
|
||||
nodes: children,
|
||||
}),
|
||||
_ => DynamicNode::Fragment(VFragment { nodes: children }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-55
@@ -131,26 +131,35 @@ impl<'a> DynamicNode<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VComponent<'a> {
|
||||
pub name: &'static str,
|
||||
pub static_props: bool,
|
||||
pub props: Cell<*mut dyn AnyProps<'a>>,
|
||||
pub placeholder: Cell<Option<ElementId>>,
|
||||
pub scope: Cell<Option<ScopeId>>,
|
||||
pub props: Cell<Option<Box<dyn AnyProps<'a> + 'a>>>,
|
||||
pub render_fn: *const (),
|
||||
}
|
||||
|
||||
impl<'a> std::fmt::Debug for VComponent<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("VComponent")
|
||||
.field("name", &self.name)
|
||||
.field("static_props", &self.static_props)
|
||||
.field("placeholder", &self.placeholder)
|
||||
.field("scope", &self.scope)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VText<'a> {
|
||||
pub id: Cell<ElementId>,
|
||||
pub value: &'a str,
|
||||
pub inner: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VFragment<'a> {
|
||||
pub nodes: &'a [VNode<'a>],
|
||||
pub inner: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -268,54 +277,3 @@ fn what_are_the_sizes() {
|
||||
dbg!(std::mem::size_of::<Template>());
|
||||
dbg!(std::mem::size_of::<TemplateNode>());
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
|
||||
SSR includes data-id which allows O(1) hydration
|
||||
|
||||
|
||||
we read the edit stream dn then we can just rehydare
|
||||
|
||||
|
||||
|
||||
ideas:
|
||||
- IDs for lookup
|
||||
- use edit stream to hydrate
|
||||
- write comments to dom that specify size of children
|
||||
|
||||
IDs for lookups
|
||||
- adds noise to generated html
|
||||
- doesnt work for text nodes
|
||||
- suspense could cause ordering to be weird
|
||||
|
||||
Names for lookups:
|
||||
- label each root or something with the template name
|
||||
- label each dynamic node with a path
|
||||
- noisy too
|
||||
- allows reverse lookups
|
||||
|
||||
Ideal:
|
||||
- no noise in the dom
|
||||
- fast, ideally O(1)
|
||||
- able to pick apart text nodes that get merged during SSR
|
||||
|
||||
|
||||
--> render vdom
|
||||
--> traverse vdom and real dom simultaneously
|
||||
|
||||
IE
|
||||
|
||||
div {
|
||||
div {
|
||||
div {
|
||||
"thing"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
@@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
any_props::AnyProps,
|
||||
bump_frame::BumpFrame,
|
||||
diff::DirtyScope,
|
||||
factory::RenderReturn,
|
||||
innerlude::{SuspenseId, SuspenseLeaf},
|
||||
scheduler::RcWake,
|
||||
@@ -16,7 +17,7 @@ use std::{
|
||||
};
|
||||
|
||||
impl VirtualDom {
|
||||
pub(super) fn new_scope(&mut self, props: *mut dyn AnyProps<'static>) -> &mut ScopeState {
|
||||
pub(super) fn new_scope(&mut self, props: *const dyn AnyProps<'static>) -> &mut ScopeState {
|
||||
let parent = self.acquire_current_scope_raw();
|
||||
let entry = self.scopes.vacant_entry();
|
||||
let height = unsafe { parent.map(|f| (*f).height).unwrap_or(0) + 1 };
|
||||
@@ -125,6 +126,12 @@ impl VirtualDom {
|
||||
// And move the render generation forward by one
|
||||
scope.render_cnt.set(scope.render_cnt.get() + 1);
|
||||
|
||||
// remove this scope from dirty scopes
|
||||
self.dirty_scopes.remove(&DirtyScope {
|
||||
height: scope.height,
|
||||
id: scope.id,
|
||||
});
|
||||
|
||||
// rebind the lifetime now that its stored internally
|
||||
unsafe { mem::transmute(alloced) }
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//! This module provides the primary mechanics to create a hook-based, concurrent VDOM for Rust.
|
||||
|
||||
use crate::{
|
||||
any_props::VComponentProps,
|
||||
any_props::VProps,
|
||||
arena::ElementId,
|
||||
arena::ElementRef,
|
||||
diff::DirtyScope,
|
||||
@@ -240,7 +240,7 @@ impl VirtualDom {
|
||||
finished_fibers: Vec::new(),
|
||||
};
|
||||
|
||||
let root = dom.new_scope(Box::into_raw(Box::new(VComponentProps::new(
|
||||
let root = dom.new_scope(Box::leak(Box::new(VProps::new(
|
||||
root,
|
||||
|_, _| unreachable!(),
|
||||
root_props,
|
||||
|
||||
Reference in new issue
Block a user