wip: clean up using new children syntax
This commit is contained in:
1 parent
d4192d0de2
commit
9c1343610b
6 files changed
+96
-85
No files matched your search
@@ -5,11 +5,7 @@
|
|||||||
//! if the type supports PartialEq. The Properties trait is used by the rsx! and html! macros to generate the type-safe builder
|
//! if the type supports PartialEq. The Properties trait is used by the rsx! and html! macros to generate the type-safe builder
|
||||||
//! that ensures compile-time required and optional fields on cx.
|
//! that ensures compile-time required and optional fields on cx.
|
||||||
|
|
||||||
use crate::{
|
use crate::innerlude::{Context, Element, VNode};
|
||||||
innerlude::{Context, Element, FC},
|
|
||||||
NodeFactory, VNode,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A component is a wrapper around a Context and some Props that share a lifetime
|
/// A component is a wrapper around a Context and some Props that share a lifetime
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@@ -44,6 +40,27 @@ use crate::{
|
|||||||
///
|
///
|
||||||
pub type Scope<'a, T> = (Context<'a>, &'a T);
|
pub type Scope<'a, T> = (Context<'a>, &'a T);
|
||||||
|
|
||||||
|
pub struct FragmentProps<'a> {
|
||||||
|
childen: &'a VNode<'a>,
|
||||||
|
}
|
||||||
|
pub struct FragmentPropsBuilder<'a> {
|
||||||
|
childen: Option<&'a VNode<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Properties for FragmentProps<'a> {
|
||||||
|
type Builder = FragmentPropsBuilder<'a>;
|
||||||
|
|
||||||
|
const IS_STATIC: bool = false;
|
||||||
|
|
||||||
|
fn builder() -> Self::Builder {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn memoize(&self, other: &Self) -> bool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Create inline fragments using Component syntax.
|
/// Create inline fragments using Component syntax.
|
||||||
///
|
///
|
||||||
/// Fragments capture a series of children without rendering extra nodes.
|
/// Fragments capture a series of children without rendering extra nodes.
|
||||||
@@ -66,11 +83,8 @@ pub type Scope<'a, T> = (Context<'a>, &'a T);
|
|||||||
/// You want to use this free-function when your fragment needs a key and simply returning multiple nodes from rsx! won't cut it.
|
/// You want to use this free-function when your fragment needs a key and simply returning multiple nodes from rsx! won't cut it.
|
||||||
///
|
///
|
||||||
#[allow(non_upper_case_globals, non_snake_case)]
|
#[allow(non_upper_case_globals, non_snake_case)]
|
||||||
pub fn Fragment<'a>((cx, _): Scope<'a, ()>) -> Element<'a> {
|
pub fn Fragment<'a>((_, props): Scope<'a, FragmentProps<'a>>) -> Element<'a> {
|
||||||
todo!()
|
Some(props.childen.decouple())
|
||||||
// let p: Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_> =
|
|
||||||
// Box::new(|f: NodeFactory| f.fragment_from_iter(cx.children()));
|
|
||||||
// cx.render(p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Every "Props" used for a component must implement the `Properties` trait. This trait gives some hints to Dioxus
|
/// Every "Props" used for a component must implement the `Properties` trait. This trait gives some hints to Dioxus
|
||||||
|
|||||||
@@ -420,10 +420,6 @@ impl<'bump> DiffMachine<'bump> {
|
|||||||
) => self
|
) => self
|
||||||
.stack
|
.stack
|
||||||
.create_node(new_node, MountType::Replace { old: old_node }),
|
.create_node(new_node, MountType::Replace { old: old_node }),
|
||||||
|
|
||||||
(Placeholder, _) | (_, Placeholder) => {
|
|
||||||
unreachable!("placeholder should never be diffed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,18 @@
|
|||||||
use std::mem;
|
//! Support for storing lazy-nodes on the stack
|
||||||
|
//!
|
||||||
|
//! This module provides support for a type called `LazyNodes` which is a micro-heap located on the stack to make calls
|
||||||
|
//! to `rsx!` more efficient.
|
||||||
|
//!
|
||||||
|
//! To support returning rsx! from branches in match statements, we need to use dynamic dispatch on NodeFactory closures.
|
||||||
|
//!
|
||||||
|
//! This can be done either through boxing directly, or by using dynamic-sized-types and a custom allocator. In our case,
|
||||||
|
//! we build a tiny alloactor in the stack and allocate the closure into that.
|
||||||
|
//!
|
||||||
|
//! The logic for this was borrowed from https://docs.rs/stack_dst/0.6.1/stack_dst/. Unfortunately, this crate does not
|
||||||
|
//! support non-static closures, so we've implemented the core logic of `ValueA` in this module.
|
||||||
|
|
||||||
/*
|
|
||||||
Remember: calls to rsx! are lazy - they are not evaluated immediately.
|
|
||||||
|
|
||||||
They also using dynamic dispatch, so we can return multiple rsx!'s from match statements and such.
|
|
||||||
|
|
||||||
If we allocated every rsx! call on the heap, it would be quite wasteful. Rsx! calls are FnOnce, so they can be stored in a stack.
|
|
||||||
|
|
||||||
Solutions like stackdst are useful, but they only support 'static closures.
|
|
||||||
|
|
||||||
All our closures are bound by the bump lifetime, so stack-dst will not work for us
|
|
||||||
|
|
||||||
Our solution is to try and manually allocate the closure onto the stack.
|
|
||||||
If it fails, then we default to Box.
|
|
||||||
|
|
||||||
*/
|
|
||||||
use crate::innerlude::{NodeFactory, VNode};
|
use crate::innerlude::{NodeFactory, VNode};
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
/// A concrete type provider for closures that build VNode structures.
|
/// A concrete type provider for closures that build VNode structures.
|
||||||
///
|
///
|
||||||
@@ -73,13 +70,13 @@ impl<'a, 'b> LazyNodes<'a, 'b> {
|
|||||||
let size = mem::size_of::<F>();
|
let size = mem::size_of::<F>();
|
||||||
|
|
||||||
if info.len() * mem::size_of::<usize>() + size > mem::size_of::<StackHeapSize>() {
|
if info.len() * mem::size_of::<usize>() + size > mem::size_of::<StackHeapSize>() {
|
||||||
log::error!("lazy nodes was too large to fit into stack. falling back to heap");
|
log::debug!("lazy nodes was too large to fit into stack. falling back to heap");
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
inner: StackNodeStorage::Heap(Box::new(val)),
|
inner: StackNodeStorage::Heap(Box::new(val)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::error!("lazy nodes fits on stack!");
|
log::debug!("lazy nodes fits on stack!");
|
||||||
let mut buf: StackHeapSize = [0; 12];
|
let mut buf: StackHeapSize = [0; 12];
|
||||||
|
|
||||||
assert!(info.len() + round_to_words(size) <= buf.as_ref().len());
|
assert!(info.len() + round_to_words(size) <= buf.as_ref().len());
|
||||||
@@ -173,3 +170,22 @@ unsafe fn make_fat_ptr<T: ?Sized>(data_ptr: usize, meta_vals: &[usize]) -> *mut
|
|||||||
fn round_to_words(len: usize) -> usize {
|
fn round_to_words(len: usize) -> usize {
|
||||||
(len + mem::size_of::<usize>() - 1) / mem::size_of::<usize>()
|
(len + mem::size_of::<usize>() - 1) / mem::size_of::<usize>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
let bump = bumpalo::Bump::new();
|
||||||
|
|
||||||
|
simple_logger::init();
|
||||||
|
|
||||||
|
let factory = NodeFactory { bump: &bump };
|
||||||
|
|
||||||
|
let caller = NodeFactory::annotate_lazy(|f| {
|
||||||
|
//
|
||||||
|
f.text(format_args!("hello world!"))
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let g = caller.call(factory);
|
||||||
|
|
||||||
|
dbg!(g);
|
||||||
|
}
|
||||||
@@ -155,6 +155,22 @@ impl<'src> VNode<'src> {
|
|||||||
VNode::Component(_) => None,
|
VNode::Component(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create an "owned" version of the vnode.
|
||||||
|
pub fn decouple(&self) -> VNode<'src> {
|
||||||
|
match self {
|
||||||
|
VNode::Text(t) => VNode::Text(*t),
|
||||||
|
VNode::Element(e) => VNode::Element(*e),
|
||||||
|
VNode::Component(c) => VNode::Component(*c),
|
||||||
|
VNode::Suspended(s) => VNode::Suspended(*s),
|
||||||
|
VNode::Anchor(a) => VNode::Anchor(*a),
|
||||||
|
VNode::Fragment(f) => VNode::Fragment(VFragment {
|
||||||
|
children: f.children,
|
||||||
|
key: f.key,
|
||||||
|
is_static: f.is_static,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A placeholder node only generated when Fragments don't have any children.
|
/// A placeholder node only generated when Fragments don't have any children.
|
||||||
|
|||||||
+13
-13
@@ -341,21 +341,21 @@ impl ScopeInner {
|
|||||||
|
|
||||||
// Todo: see if we can add stronger guarantees around internal bookkeeping and failed component renders.
|
// Todo: see if we can add stronger guarantees around internal bookkeeping and failed component renders.
|
||||||
//
|
//
|
||||||
todo!()
|
// todo!()
|
||||||
// if let Some(builder) = render(self) {
|
if let Some(builder) = render(self) {
|
||||||
// let new_head = builder.into_vnode(NodeFactory {
|
let new_head = builder.into_vnode(NodeFactory {
|
||||||
// bump: &self.frames.wip_frame().bump,
|
bump: &self.frames.wip_frame().bump,
|
||||||
// });
|
});
|
||||||
// log::debug!("Render is successful");
|
log::debug!("Render is successful");
|
||||||
|
|
||||||
// // the user's component succeeded. We can safely cycle to the next frame
|
// the user's component succeeded. We can safely cycle to the next frame
|
||||||
// self.frames.wip_frame_mut().head_node = unsafe { std::mem::transmute(new_head) };
|
self.frames.wip_frame_mut().head_node = unsafe { std::mem::transmute(new_head) };
|
||||||
// self.frames.cycle_frame();
|
self.frames.cycle_frame();
|
||||||
|
|
||||||
// true
|
true
|
||||||
// } else {
|
} else {
|
||||||
// false
|
false
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,27 +21,13 @@ impl TestDom {
|
|||||||
NodeFactory::new(&self.bump)
|
NodeFactory::new(&self.bump)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_direct<'a>(
|
pub fn render_direct<'a>(&'a self, lazy_nodes: Option<LazyNodes<'a, '_>>) -> VNode<'a> {
|
||||||
&'a self,
|
lazy_nodes.into_vnode(NodeFactory::new(&self.bump))
|
||||||
lazy_nodes: Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_>>,
|
|
||||||
) -> VNode<'a>
|
|
||||||
// where
|
|
||||||
// F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
// lazy_nodes.into_vnode(NodeFactory::new(&self.bump))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render<'a>(
|
pub fn render<'a>(&'a self, lazy_nodes: Option<LazyNodes<'a, '_>>) -> &'a VNode<'a> {
|
||||||
&'a self,
|
self.bump
|
||||||
lazy_nodes: Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_>>,
|
.alloc(lazy_nodes.into_vnode(NodeFactory::new(&self.bump)))
|
||||||
) -> &'a VNode<'a>
|
|
||||||
// where
|
|
||||||
// F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
|
|
||||||
{
|
|
||||||
todo!()
|
|
||||||
// self.bump
|
|
||||||
// .alloc(lazy_nodes.into_vnode(NodeFactory::new(&self.bump)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn diff<'a>(&'a self, old: &'a VNode<'a>, new: &'a VNode<'a>) -> Mutations<'a> {
|
pub fn diff<'a>(&'a self, old: &'a VNode<'a>, new: &'a VNode<'a>) -> Mutations<'a> {
|
||||||
@@ -51,14 +37,7 @@ impl TestDom {
|
|||||||
machine.mutations
|
machine.mutations
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create<'a>(
|
pub fn create<'a>(&'a self, left: Option<LazyNodes<'a, '_>>) -> Mutations<'a> {
|
||||||
&'a self,
|
|
||||||
left: Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_>>,
|
|
||||||
) -> Mutations<'a>
|
|
||||||
// pub fn create<'a, F1>(&'a self, left: LazyNodes<'a, F1>) -> Mutations<'a>
|
|
||||||
// where
|
|
||||||
// F1: FnOnce(NodeFactory<'a>) -> VNode<'a>,
|
|
||||||
{
|
|
||||||
let old = self.bump.alloc(self.render_direct(left));
|
let old = self.bump.alloc(self.render_direct(left));
|
||||||
|
|
||||||
let mut machine = DiffMachine::new(Mutations::new(), &self.scheduler.pool);
|
let mut machine = DiffMachine::new(Mutations::new(), &self.scheduler.pool);
|
||||||
@@ -72,13 +51,9 @@ impl TestDom {
|
|||||||
|
|
||||||
pub fn lazy_diff<'a>(
|
pub fn lazy_diff<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
left: Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_>>,
|
left: Option<LazyNodes<'a, '_>>,
|
||||||
right: Option<Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + '_>>,
|
right: Option<LazyNodes<'a, '_>>,
|
||||||
) -> (Mutations<'a>, Mutations<'a>)
|
) -> (Mutations<'a>, Mutations<'a>) {
|
||||||
// where
|
|
||||||
// F1: FnOnce(NodeFactory<'a>) -> VNode<'a>,
|
|
||||||
// F2: FnOnce(NodeFactory<'a>) -> VNode<'a>,
|
|
||||||
{
|
|
||||||
let (old, new) = (self.render(left), self.render(right));
|
let (old, new) = (self.render(left), self.render(right));
|
||||||
|
|
||||||
let mut machine = DiffMachine::new(Mutations::new(), &self.scheduler.pool);
|
let mut machine = DiffMachine::new(Mutations::new(), &self.scheduler.pool);
|
||||||
@@ -105,9 +80,3 @@ impl Default for TestDom {
|
|||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VirtualDom {
|
|
||||||
pub fn simulate(&mut self) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user