wip: fix issues with lifetimes
this commit fixes some lifetime issues regarding having to "move" data into the IntoVNode closure.
This commit is contained in:
1 parent
22e659c2bd
commit
a38a81e129
39 files changed
+566
-255
No files matched your search
@@ -49,10 +49,23 @@ pub fn fc_to_builder<T: Properties>(_: FC<T>) -> T::Builder {
|
||||
///
|
||||
/// Fragments are incredibly useful when necessary, but *do* add cost in the diffing phase.
|
||||
/// Try to avoid nesting fragments if you can. Infinitely nested Fragments *will* cause diffing to crash.
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const Fragment: FC<()> = |cx| {
|
||||
use crate::prelude::*;
|
||||
cx.render(LazyNodes::new(move |c| {
|
||||
crate::nodebuilder::vfragment(c, None, cx.children())
|
||||
use crate::prelude::*;
|
||||
pub fn Fragment<'a>(cx: Context<'a, ()>) -> VNode<'a> {
|
||||
let childs: &'a [VNode<'a>] = cx.children();
|
||||
cx.render(LazyNodes::new({
|
||||
move |f| {
|
||||
//
|
||||
f.fragment_from_iter(childs)
|
||||
}
|
||||
}))
|
||||
};
|
||||
}
|
||||
// #[allow(non_upper_case_globals)]
|
||||
// pub const Fragment: FC<()> = |cx| {
|
||||
// use crate::prelude::*;
|
||||
// let childs = cx.children();
|
||||
// cx.render(LazyNodes::new(move |c| {
|
||||
// c.fragment_from_iter(childs)
|
||||
// // c.text(format_args!(""))
|
||||
// // crate::nodebuilder::vfragment(c, None, cx.children())
|
||||
// }))
|
||||
// };
|
||||
@@ -49,18 +49,18 @@ impl DebugRenderer {
|
||||
// If you have a list or "nth" child, you do need to list those children, but you don't need to
|
||||
// fill in their children/attrs/etc
|
||||
// Does not handle children or lifecycles and will always fail the test if they show up in the rhs
|
||||
pub fn compare<'a, F>(&self, other: LazyNodes<'a, F>) -> Result<()>
|
||||
pub fn compare<F>(&self, other: LazyNodes<F>) -> Result<()>
|
||||
where
|
||||
F: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
|
||||
F: for<'b, 'c> FnOnce(&'b NodeFactory<'c>) -> VNode<'c>,
|
||||
{
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Do a full compare - everything must match
|
||||
// Ignores listeners and children components
|
||||
pub fn compare_full<'a, F>(&self, other: LazyNodes<'a, F>) -> Result<()>
|
||||
pub fn compare_full<F>(&self, other: LazyNodes<F>) -> Result<()>
|
||||
where
|
||||
F: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
|
||||
F: for<'b, 'c> FnOnce(&'b NodeFactory<'c>) -> VNode<'c>,
|
||||
{
|
||||
Ok(())
|
||||
}
|
||||
@@ -69,9 +69,9 @@ impl DebugRenderer {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn render_nodes<'a, F>(&self, other: LazyNodes<'a, F>) -> Result<()>
|
||||
pub fn render_nodes<F>(&self, other: LazyNodes<F>) -> Result<()>
|
||||
where
|
||||
F: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
|
||||
F: for<'b, 'c> FnOnce(&'b NodeFactory<'c>) -> VNode<'c>,
|
||||
{
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+195
-66
@@ -124,14 +124,12 @@ pub mod on {
|
||||
|
||||
macro_rules! event_directory {
|
||||
( $(
|
||||
$(
|
||||
#[$attr:meta]
|
||||
)*
|
||||
$( #[$attr:meta] )*
|
||||
$eventdata:ident($wrapper:ident): [
|
||||
$(
|
||||
#[$method_attr:meta]
|
||||
$( #[$method_attr:meta] )*
|
||||
$name:ident
|
||||
)*
|
||||
$( $name:ident )*
|
||||
];
|
||||
)* ) => {
|
||||
$(
|
||||
@@ -149,8 +147,8 @@ pub mod on {
|
||||
}
|
||||
}
|
||||
|
||||
$(#[$method_attr])*
|
||||
$(
|
||||
$(#[$method_attr])*
|
||||
pub fn $name<'a>(
|
||||
c: &'_ NodeFactory<'a>,
|
||||
callback: impl Fn($wrapper) + 'a,
|
||||
@@ -181,35 +179,51 @@ pub mod on {
|
||||
//
|
||||
//
|
||||
event_directory! {
|
||||
|
||||
|
||||
|
||||
|
||||
ClipboardEventInner(ClipboardEvent): [
|
||||
/// Called when "copy"
|
||||
oncopy
|
||||
/// oncut
|
||||
oncut
|
||||
/// onpaste
|
||||
onpaste
|
||||
];
|
||||
|
||||
CompositionEventInner(CompositionEvent): [
|
||||
/// oncompositionend
|
||||
oncompositionend
|
||||
/// oncompositionstart
|
||||
oncompositionstart
|
||||
/// oncompositionupdate
|
||||
oncompositionupdate
|
||||
];
|
||||
|
||||
KeyboardEventInner(KeyboardEvent): [
|
||||
/// onkeydown
|
||||
onkeydown
|
||||
/// onkeypress
|
||||
onkeypress
|
||||
/// onkeyup
|
||||
onkeyup
|
||||
];
|
||||
|
||||
FocusEventInner(FocusEvent): [
|
||||
/// onfocus
|
||||
onfocus
|
||||
/// onblur
|
||||
onblur
|
||||
];
|
||||
|
||||
|
||||
FormEventInner(FormEvent): [
|
||||
/// onchange
|
||||
onchange
|
||||
/// oninput
|
||||
oninput
|
||||
/// oninvalid
|
||||
oninvalid
|
||||
/// onreset
|
||||
onreset
|
||||
/// onsubmit
|
||||
onsubmit
|
||||
];
|
||||
|
||||
@@ -237,63 +251,202 @@ pub mod on {
|
||||
/// ```
|
||||
///
|
||||
/// ## Event Handlers
|
||||
/// - click
|
||||
/// - contextmenu
|
||||
/// - doubleclick
|
||||
/// - drag
|
||||
/// - dragend
|
||||
/// - dragenter
|
||||
/// - dragexit
|
||||
/// - dragleave
|
||||
/// - dragover
|
||||
/// - dragstart
|
||||
/// - drop
|
||||
/// - mousedown
|
||||
/// - mouseenter
|
||||
/// - mouseleave
|
||||
/// - mousemove
|
||||
/// - mouseout
|
||||
/// - mouseover
|
||||
/// - mouseup
|
||||
/// - [`onclick`]
|
||||
/// - [`oncontextmenu`]
|
||||
/// - [`ondoubleclick`]
|
||||
/// - [`ondrag`]
|
||||
/// - [`ondragend`]
|
||||
/// - [`ondragenter`]
|
||||
/// - [`ondragexit`]
|
||||
/// - [`ondragleave`]
|
||||
/// - [`ondragover`]
|
||||
/// - [`ondragstart`]
|
||||
/// - [`ondrop`]
|
||||
/// - [`onmousedown`]
|
||||
/// - [`onmouseenter`]
|
||||
/// - [`onmouseleave`]
|
||||
/// - [`onmousemove`]
|
||||
/// - [`onmouseout`]
|
||||
/// - [`onmouseover`]
|
||||
/// - [`onmouseup`]
|
||||
MouseEventInner(MouseEvent): [
|
||||
/// Onclick!
|
||||
/// Execute a callback when a button is clicked.
|
||||
///
|
||||
/// ## Description
|
||||
///
|
||||
/// An element receives a click event when a pointing device button (such as a mouse's primary mouse button)
|
||||
/// is both pressed and released while the pointer is located inside the element.
|
||||
///
|
||||
/// - Bubbles: Yes
|
||||
/// - Cancelable: Yes
|
||||
/// - Interface: [`MouseEvent`]
|
||||
///
|
||||
/// If the button is pressed on one element and the pointer is moved outside the element before the button
|
||||
/// is released, the event is fired on the most specific ancestor element that contained both elements.
|
||||
/// `click` fires after both the `mousedown` and `mouseup` events have fired, in that order.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// rsx!( button { "click me", onclick: move |_| log::info!("Clicked!`") } )
|
||||
/// ```
|
||||
///
|
||||
/// ## Reference
|
||||
/// - https://www.w3schools.com/tags/ev_onclick.asp
|
||||
/// - https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event
|
||||
///
|
||||
onclick
|
||||
/// oncontextmenu
|
||||
oncontextmenu
|
||||
/// ondoubleclick
|
||||
ondoubleclick
|
||||
/// ondrag
|
||||
ondrag
|
||||
/// ondragend
|
||||
ondragend
|
||||
/// ondragenter
|
||||
ondragenter
|
||||
/// ondragexit
|
||||
ondragexit
|
||||
/// ondragleave
|
||||
ondragleave
|
||||
/// ondragover
|
||||
ondragover
|
||||
/// ondragstart
|
||||
ondragstart
|
||||
/// ondrop
|
||||
ondrop
|
||||
/// onmousedown
|
||||
onmousedown
|
||||
/// onmouseenter
|
||||
onmouseenter
|
||||
/// onmouseleave
|
||||
onmouseleave
|
||||
/// onmousemove
|
||||
onmousemove
|
||||
/// onmouseout
|
||||
onmouseout
|
||||
/// onmouseover
|
||||
onmouseover
|
||||
/// onmouseup
|
||||
onmouseup
|
||||
];
|
||||
|
||||
PointerEventInner(PointerEvent): [
|
||||
pointerdown pointermove pointerup pointercancel gotpointercapture
|
||||
lostpointercapture pointerenter pointerleave pointerover pointerout
|
||||
/// pointerdown
|
||||
onpointerdown
|
||||
/// pointermove
|
||||
onpointermove
|
||||
/// pointerup
|
||||
onpointerup
|
||||
/// pointercancel
|
||||
onpointercancel
|
||||
/// gotpointercapture
|
||||
ongotpointercapture
|
||||
/// lostpointercapture
|
||||
onlostpointercapture
|
||||
/// pointerenter
|
||||
onpointerenter
|
||||
/// pointerleave
|
||||
onpointerleave
|
||||
/// pointerover
|
||||
onpointerover
|
||||
/// pointerout
|
||||
onpointerout
|
||||
];
|
||||
SelectionEventInner(SelectionEvent): [select];
|
||||
TouchEventInner(TouchEvent): [touchcancel touchend touchmove touchstart];
|
||||
UIEventInner(UIEvent): [scroll];
|
||||
WheelEventInner(WheelEvent): [wheel];
|
||||
|
||||
SelectionEventInner(SelectionEvent): [
|
||||
/// onselect
|
||||
onselect
|
||||
];
|
||||
|
||||
TouchEventInner(TouchEvent): [
|
||||
/// ontouchcancel
|
||||
ontouchcancel
|
||||
/// ontouchend
|
||||
ontouchend
|
||||
/// ontouchmove
|
||||
ontouchmove
|
||||
/// ontouchstart
|
||||
ontouchstart
|
||||
];
|
||||
|
||||
UIEventInner(UIEvent): [
|
||||
///
|
||||
scroll
|
||||
];
|
||||
|
||||
WheelEventInner(WheelEvent): [
|
||||
///
|
||||
wheel
|
||||
];
|
||||
|
||||
MediaEventInner(MediaEvent): [
|
||||
abort canplay canplaythrough durationchange emptied encrypted
|
||||
ended error loadeddata loadedmetadata loadstart pause play
|
||||
playing progress ratechange seeked seeking stalled suspend
|
||||
timeupdate volumechange waiting
|
||||
///abort
|
||||
onabort
|
||||
///canplay
|
||||
oncanplay
|
||||
///canplaythrough
|
||||
oncanplaythrough
|
||||
///durationchange
|
||||
ondurationchange
|
||||
///emptied
|
||||
onemptied
|
||||
///encrypted
|
||||
onencrypted
|
||||
///ended
|
||||
onended
|
||||
///error
|
||||
onerror
|
||||
///loadeddata
|
||||
onloadeddata
|
||||
///loadedmetadata
|
||||
onloadedmetadata
|
||||
///loadstart
|
||||
onloadstart
|
||||
///pause
|
||||
onpause
|
||||
///play
|
||||
onplay
|
||||
///playing
|
||||
onplaying
|
||||
///progress
|
||||
onprogress
|
||||
///ratechange
|
||||
onratechange
|
||||
///seeked
|
||||
onseeked
|
||||
///seeking
|
||||
onseeking
|
||||
///stalled
|
||||
onstalled
|
||||
///suspend
|
||||
onsuspend
|
||||
///timeupdate
|
||||
ontimeupdate
|
||||
///volumechange
|
||||
onvolumechange
|
||||
///waiting
|
||||
onwaiting
|
||||
];
|
||||
|
||||
AnimationEventInner(AnimationEvent): [
|
||||
/// onanimationstart
|
||||
onanimationstart
|
||||
/// onanimationend
|
||||
onanimationend
|
||||
/// onanimationiteration
|
||||
onanimationiteration
|
||||
];
|
||||
|
||||
TransitionEventInner(TransitionEvent): [
|
||||
///
|
||||
ontransitionend
|
||||
];
|
||||
|
||||
ToggleEventInner(ToggleEvent): [
|
||||
///
|
||||
ontoggle
|
||||
];
|
||||
AnimationEventInner(AnimationEvent): [animationstart animationend animationiteration];
|
||||
TransitionEventInner(TransitionEvent): [transitionend];
|
||||
ToggleEventInner(ToggleEvent): [toggle];
|
||||
}
|
||||
|
||||
pub trait GenericEventInner {
|
||||
@@ -404,7 +557,6 @@ pub mod on {
|
||||
fn alt_key(&self) -> bool;
|
||||
fn button(&self) -> i16;
|
||||
fn buttons(&self) -> u16;
|
||||
|
||||
/// Get the X coordinate of the mouse relative to the window
|
||||
fn client_x(&self) -> i32;
|
||||
fn client_y(&self) -> i32;
|
||||
@@ -709,26 +861,3 @@ pub mod on {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mod tests {
|
||||
|
||||
// use std::rc::Rc;
|
||||
|
||||
// use crate as dioxus;
|
||||
// use crate::events::on::MouseEvent;
|
||||
// use crate::prelude::*;
|
||||
|
||||
// fn autocomplete() {
|
||||
// // let v = move |evt| {
|
||||
// // let r = evt.alt_key();
|
||||
// // };
|
||||
|
||||
// let g = rsx! {
|
||||
// button {
|
||||
// onclick: move |evt| {
|
||||
// let r = evt.alt_key();
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
@@ -16,7 +16,7 @@ pub mod component;
|
||||
pub mod styles;
|
||||
pub mod util; // Logic for extending FC
|
||||
|
||||
pub mod debug_renderer;
|
||||
// pub mod debug_renderer;
|
||||
pub mod diff;
|
||||
|
||||
pub mod error; // Error type we expose to the renderers
|
||||
@@ -62,7 +62,6 @@ pub mod prelude {
|
||||
|
||||
pub use crate::nodebuilder::LazyNodes;
|
||||
|
||||
pub use crate::nodebuilder::ChildrenList;
|
||||
pub use crate::nodebuilder::{DioxusElement, NodeFactory};
|
||||
// pub use nodes::iterables::IterableNodes;
|
||||
/// This type alias is an internal way of abstracting over the static functions that represent components.
|
||||
|
||||
@@ -6,6 +6,7 @@ use std::{
|
||||
cell::{Cell, RefCell},
|
||||
fmt::Arguments,
|
||||
intrinsics::transmute,
|
||||
marker::PhantomData,
|
||||
u128,
|
||||
};
|
||||
|
||||
@@ -511,8 +512,9 @@ where
|
||||
pub fn iter_child(mut self, nodes: impl IntoIterator<Item = impl IntoVNode<'a>>) -> Self {
|
||||
let len_before = self.children.len();
|
||||
for item in nodes {
|
||||
let child = item.into_vnode(&self.cx);
|
||||
self.children.push(child);
|
||||
todo!()
|
||||
// let child = item.into_vnode(&self.cx);
|
||||
// self.children.push(child);
|
||||
}
|
||||
if cfg!(debug_assertions) {
|
||||
if self.children.len() > len_before + 1 {
|
||||
@@ -541,52 +543,53 @@ impl<'a> IntoIterator for VNode<'a> {
|
||||
}
|
||||
}
|
||||
impl<'a> IntoVNode<'a> for VNode<'a> {
|
||||
fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a> {
|
||||
fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoVNode<'a> for &VNode<'a> {
|
||||
fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a> {
|
||||
fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a>
|
||||
// where
|
||||
// 'a: 'c,
|
||||
{
|
||||
todo!()
|
||||
// cloning is cheap since vnodes are just references into bump arenas
|
||||
self.clone()
|
||||
// self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoVNode<'a> {
|
||||
fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a>;
|
||||
fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a>;
|
||||
}
|
||||
|
||||
pub trait VNodeBuilder<'a, G>: IntoIterator<Item = G>
|
||||
where
|
||||
G: IntoVNode<'a>,
|
||||
{
|
||||
}
|
||||
// pub trait VNodeBuilder<'a, G>: IntoIterator<Item = G>
|
||||
// where
|
||||
// G: IntoVNode<'a>,
|
||||
// {
|
||||
// }
|
||||
|
||||
impl<'a, F> VNodeBuilder<'a, LazyNodes<'a, F>> for LazyNodes<'a, F> where
|
||||
F: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a
|
||||
{
|
||||
}
|
||||
// impl<'a, F> VNodeBuilder<'a, LazyNodes<F>> for LazyNodes<F> where F: FnOnce(NodeFactory) -> VNode {}
|
||||
|
||||
// Wrap the the node-builder closure in a concrete type.
|
||||
// ---
|
||||
// This is a bit of a hack to implement the IntoVNode trait for closure types.
|
||||
pub struct LazyNodes<'a, G>
|
||||
where
|
||||
G: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
|
||||
G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
|
||||
{
|
||||
inner: G,
|
||||
_p: std::marker::PhantomData<&'a ()>,
|
||||
_p: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
impl<'a, G> LazyNodes<'a, G>
|
||||
where
|
||||
G: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
|
||||
G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
|
||||
{
|
||||
pub fn new(f: G) -> Self {
|
||||
Self {
|
||||
inner: f,
|
||||
_p: std::default::Default::default(),
|
||||
_p: PhantomData {},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -598,9 +601,9 @@ where
|
||||
// rsx! { {nodes } }
|
||||
impl<'a, G> IntoVNode<'a> for LazyNodes<'a, G>
|
||||
where
|
||||
G: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
|
||||
G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
|
||||
{
|
||||
fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a> {
|
||||
fn into_vnode(self, cx: NodeFactory<'a>) -> VNode<'a> {
|
||||
(self.inner)(cx)
|
||||
}
|
||||
}
|
||||
@@ -608,7 +611,7 @@ where
|
||||
// Required because anything that enters brackets in the rsx! macro needs to implement IntoIterator
|
||||
impl<'a, G> IntoIterator for LazyNodes<'a, G>
|
||||
where
|
||||
G: for<'b> FnOnce(&'b NodeFactory<'a>) -> VNode<'a> + 'a,
|
||||
G: FnOnce(NodeFactory<'a>) -> VNode<'a>,
|
||||
{
|
||||
type Item = Self;
|
||||
type IntoIter = std::iter::Once<Self::Item>;
|
||||
@@ -617,23 +620,23 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoVNode<'a> for () {
|
||||
fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a> {
|
||||
todo!();
|
||||
VNode::Suspended {
|
||||
real: Cell::new(RealDomNode::empty()),
|
||||
}
|
||||
}
|
||||
}
|
||||
// impl IntoVNode<'_> for () {
|
||||
// fn into_vnode<'a>(self, cx: NodeFactory<'a>) -> VNode<'a> {
|
||||
// todo!();
|
||||
// VNode::Suspended {
|
||||
// real: Cell::new(RealDomNode::empty()),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<'a> IntoVNode<'a> for Option<()> {
|
||||
fn into_vnode(self, cx: &NodeFactory<'a>) -> VNode<'a> {
|
||||
todo!();
|
||||
VNode::Suspended {
|
||||
real: Cell::new(RealDomNode::empty()),
|
||||
}
|
||||
}
|
||||
}
|
||||
// impl IntoVNode<'_> for Option<()> {
|
||||
// fn into_vnode<'a>(self, cx: NodeFactory<'a>) -> VNode<'a> {
|
||||
// todo!();
|
||||
// VNode::Suspended {
|
||||
// real: Cell::new(RealDomNode::empty()),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Construct a text VNode.
|
||||
///
|
||||
@@ -702,7 +705,7 @@ pub fn attr<'a>(name: &'static str, value: &'a str) -> Attribute<'a> {
|
||||
}
|
||||
|
||||
pub fn virtual_child<'a, T: Properties + 'a>(
|
||||
cx: &NodeFactory<'a>,
|
||||
cx: NodeFactory<'a>,
|
||||
f: FC<T>,
|
||||
props: T,
|
||||
key: Option<&'a str>, // key: NodeKey<'a>,
|
||||
@@ -713,54 +716,28 @@ pub fn virtual_child<'a, T: Properties + 'a>(
|
||||
// todo!()
|
||||
VNode::Component(
|
||||
cx.bump()
|
||||
.alloc(crate::nodes::VComponent::new(cx, f, props, key, children)),
|
||||
.alloc(crate::nodes::VComponent::new(&cx, f, props, key, children)),
|
||||
// cx.bump()
|
||||
// .alloc(crate::nodes::VComponent::new(f, props, key)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn vfragment<'a>(
|
||||
cx: &NodeFactory<'a>,
|
||||
cx: NodeFactory<'a>,
|
||||
key: Option<&'a str>, // key: NodeKey<'a>,
|
||||
children: &'a [VNode<'a>],
|
||||
) -> VNode<'a> {
|
||||
VNode::Fragment(cx.bump().alloc(VFragment::new(key, children)))
|
||||
}
|
||||
|
||||
pub struct ChildrenList<'a, 'b> {
|
||||
cx: &'b NodeFactory<'a>,
|
||||
children: bumpalo::collections::Vec<'a, VNode<'a>>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> ChildrenList<'a, 'b> {
|
||||
pub fn new(cx: &'b NodeFactory<'a>) -> Self {
|
||||
Self {
|
||||
cx,
|
||||
children: bumpalo::collections::Vec::new_in(cx.bump()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_child(mut self, nodes: impl IntoIterator<Item = impl IntoVNode<'a>>) -> Self {
|
||||
for item in nodes {
|
||||
let child = item.into_vnode(&self.cx);
|
||||
self.children.push(child);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn finish(self) -> &'a [VNode<'a>] {
|
||||
self.children.into_bump_slice()
|
||||
}
|
||||
}
|
||||
|
||||
/// This struct provides an ergonomic API to quickly build VNodes.
|
||||
///
|
||||
/// NodeFactory is used to build VNodes in the component's memory space.
|
||||
/// This struct adds metadata to the final VNode about listeners, attributes, and children
|
||||
#[derive(Clone)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct NodeFactory<'a> {
|
||||
pub scope_ref: &'a Scope,
|
||||
pub listener_id: Cell<usize>,
|
||||
pub listener_id: &'a Cell<usize>,
|
||||
}
|
||||
|
||||
impl<'a> NodeFactory<'a> {
|
||||
@@ -791,7 +768,7 @@ impl<'a> NodeFactory<'a> {
|
||||
pub fn attr(
|
||||
&self,
|
||||
name: &'static str,
|
||||
val: Arguments<'a>,
|
||||
val: Arguments,
|
||||
namespace: Option<&'static str>,
|
||||
) -> Attribute<'a> {
|
||||
let value = raw_text(self.bump(), val);
|
||||
@@ -802,18 +779,6 @@ impl<'a> NodeFactory<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn child_list(&self) -> ChildrenList {
|
||||
ChildrenList::new(&self)
|
||||
}
|
||||
|
||||
pub fn fragment_builder<'b>(
|
||||
&'b self,
|
||||
key: Option<&'a str>,
|
||||
builder: impl FnOnce(ChildrenList<'a, 'b>) -> &'a [VNode<'a>],
|
||||
) -> VNode<'a> {
|
||||
self.fragment(builder(ChildrenList::new(&self)), key)
|
||||
}
|
||||
|
||||
pub fn fragment(&self, children: &'a [VNode<'a>], key: Option<&'a str>) -> VNode<'a> {
|
||||
VNode::Fragment(self.bump().alloc(VFragment {
|
||||
children,
|
||||
@@ -822,12 +787,12 @@ impl<'a> NodeFactory<'a> {
|
||||
}
|
||||
|
||||
pub fn fragment_from_iter(
|
||||
&self,
|
||||
self,
|
||||
node_iter: impl IntoIterator<Item = impl IntoVNode<'a>>,
|
||||
) -> VNode<'a> {
|
||||
let mut nodes = bumpalo::collections::Vec::new_in(self.bump());
|
||||
for node in node_iter.into_iter() {
|
||||
nodes.push(node.into_vnode(&self));
|
||||
nodes.push(node.into_vnode(self));
|
||||
}
|
||||
VNode::Fragment(
|
||||
self.bump()
|
||||
|
||||
@@ -393,6 +393,8 @@ pub struct Scope {
|
||||
// could also use ourborous
|
||||
hooks: RefCell<Vec<Hook>>,
|
||||
|
||||
pub(crate) listener_idx: Cell<usize>,
|
||||
|
||||
// Unsafety:
|
||||
// - is self-refenrential and therefore needs to point into the bump
|
||||
// Stores references into the listeners attached to the vnodes
|
||||
@@ -463,6 +465,7 @@ impl Scope {
|
||||
height,
|
||||
event_channel,
|
||||
arena_link,
|
||||
listener_idx: Default::default(),
|
||||
frames: ActiveFrame::new(),
|
||||
hooks: Default::default(),
|
||||
shared_contexts: Default::default(),
|
||||
@@ -506,13 +509,9 @@ impl Scope {
|
||||
|
||||
// Remove all the outdated listeners
|
||||
self.listeners.borrow_mut().clear();
|
||||
// self.listeners
|
||||
// .try_borrow_mut()
|
||||
// .ok()
|
||||
// .ok_or(Error::FatalInternal("Borrowing listener failed"))?
|
||||
// .drain(..);
|
||||
|
||||
self.hookidx.set(0);
|
||||
self.listener_idx.set(0);
|
||||
|
||||
let caller = self
|
||||
.caller
|
||||
@@ -522,12 +521,8 @@ impl Scope {
|
||||
// Cast the caller ptr from static to one with our own reference
|
||||
let c2: &OpaqueComponent = caller.as_ref();
|
||||
let c3: &OpaqueComponent = unsafe { std::mem::transmute(c2) };
|
||||
// let c2: &OpaqueComponent<'static> = caller.as_ref();
|
||||
// let c3: &OpaqueComponent<'sel> = unsafe { std::mem::transmute(c2) };
|
||||
|
||||
let unsafe_head = unsafe { self.own_vnodes(c3) };
|
||||
|
||||
self.frames.cur_frame_mut().head_node = unsafe_head;
|
||||
self.frames.cur_frame_mut().head_node = unsafe { self.own_vnodes(c3) };
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -685,13 +680,15 @@ pub trait Scoped<'src>: Sized {
|
||||
/// cx.render(lazy_tree)
|
||||
/// }
|
||||
///```
|
||||
fn render<'a, F: for<'b> FnOnce(&'b NodeFactory<'src>) -> VNode<'src> + 'src + 'a>(
|
||||
fn render<F: FnOnce(NodeFactory<'src>) -> VNode<'src>>(
|
||||
self,
|
||||
lazy_nodes: LazyNodes<'src, F>,
|
||||
) -> VNode<'src> {
|
||||
lazy_nodes.into_vnode(&NodeFactory {
|
||||
scope_ref: self.get_scope(),
|
||||
listener_id: 0.into(),
|
||||
let scope_ref = self.get_scope();
|
||||
let listener_id = &scope_ref.listener_idx;
|
||||
lazy_nodes.into_vnode(NodeFactory {
|
||||
scope_ref,
|
||||
listener_id,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -890,14 +887,14 @@ Any function prefixed with "use" should not be called conditionally.
|
||||
#[derive(Clone)]
|
||||
pub struct SuspendedContext {}
|
||||
|
||||
impl SuspendedContext {
|
||||
pub fn render<'a, 'src, F: for<'b> FnOnce(&'b NodeFactory<'src>) -> VNode<'src> + 'src + 'a>(
|
||||
self,
|
||||
lazy_nodes: LazyNodes<'src, F>,
|
||||
) -> VNode<'src> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
// impl SuspendedContext {
|
||||
// pub fn render<'a, F: for<'b, 'src> FnOnce(&'b NodeFactory<'src>) -> VNode<'src>>(
|
||||
// &self,
|
||||
// lazy_nodes: LazyNodes<F>,
|
||||
// ) -> VNode {
|
||||
// todo!()
|
||||
// }
|
||||
// }
|
||||
|
||||
// ==================================================================================
|
||||
// Supporting structs for the above abstractions
|
||||
|
||||
Reference in new issue
Block a user