wip: pre vnodes instead of vnode
This commit is contained in:
1 parent
e3d9db0847
commit
fe6938ceb3
21 files changed
+303
-441
No files matched your search
@@ -7,21 +7,12 @@
|
||||
|
||||
use crate::innerlude::FC;
|
||||
|
||||
pub type ScopeIdx = generational_arena::Index;
|
||||
|
||||
pub unsafe trait Properties: PartialEq + Sized {
|
||||
type Builder;
|
||||
const CAN_BE_MEMOIZED: bool;
|
||||
fn builder() -> Self::Builder;
|
||||
}
|
||||
|
||||
pub struct EmptyBuilder;
|
||||
impl EmptyBuilder {
|
||||
pub fn build(self) -> () {
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Properties for () {
|
||||
const CAN_BE_MEMOIZED: bool = true;
|
||||
type Builder = EmptyBuilder;
|
||||
@@ -31,151 +22,14 @@ unsafe impl Properties for () {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fc_to_builder<T: Properties>(_f: FC<T>) -> T::Builder {
|
||||
pub struct EmptyBuilder;
|
||||
impl EmptyBuilder {
|
||||
#[inline]
|
||||
pub fn build(self) -> () {
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fc_to_builder<T: Properties>(_: FC<T>) -> T::Builder {
|
||||
T::builder()
|
||||
}
|
||||
|
||||
mod testing {
|
||||
use std::{any::Any, ops::Deref};
|
||||
|
||||
use crate::innerlude::VNode;
|
||||
|
||||
// trait PossibleProps {
|
||||
// type POut: PartialEq;
|
||||
// fn as_partial_eq(&self) -> Option<&Self::POut> {
|
||||
// None
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl<T: PartialEq> PossibleProps for T {
|
||||
// type POut = Self;
|
||||
// }
|
||||
|
||||
// struct SomeProps2<'a> {
|
||||
// inner: &'a str,
|
||||
// }
|
||||
|
||||
// Fallback trait for to all types to default to `false`.
|
||||
trait NotEq {
|
||||
const IS_EQ: bool = false;
|
||||
}
|
||||
impl<T> NotEq for T {}
|
||||
|
||||
// Concrete wrapper type where `IS_COPY` becomes `true` if `T: Copy`.
|
||||
struct IsEq<G, T>(std::marker::PhantomData<(G, T)>);
|
||||
|
||||
impl<G: PartialEq, T: PartialEq<G>> IsEq<G, T> {
|
||||
// Because this is implemented directly on `IsCopy`, it has priority over
|
||||
// the `NotCopy` trait impl.
|
||||
//
|
||||
// Note: this is a *totally different* associated constant from that in
|
||||
// `NotCopy`. This does not specialize the `NotCopy` trait impl on `IsCopy`.
|
||||
const IS_EQ: bool = true;
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
struct SomeProps {
|
||||
inner: &'static str,
|
||||
}
|
||||
|
||||
struct SomeProps2 {
|
||||
inner: &'static str,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let g = IsEq::<SomeProps, SomeProps>::IS_EQ;
|
||||
|
||||
// let g = IsEq::<Vec<u32>>::IS_COPY;
|
||||
// let g = IsEq::<u32>::IS_COPY;
|
||||
// dbg!(g);
|
||||
|
||||
// let props = SomeProps { inner: "asd" };
|
||||
|
||||
// let intermediate: Box<dyn PartialEq<SomeProps>> = Box::new(props);
|
||||
// let as_any: Box<dyn Any> = Box::new(intermediate);
|
||||
|
||||
// let as_partialeq = as_any
|
||||
// .downcast_ref::<Box<dyn PartialEq<SomeProps>>>()
|
||||
// .unwrap();
|
||||
}
|
||||
|
||||
// struct blah {}
|
||||
// #[reorder_args]
|
||||
pub fn blah(a: i32, b: &str, c: &str) {}
|
||||
|
||||
// pub mod blah {
|
||||
// pub const a: u8 = 0;
|
||||
// pub const b: u8 = 1;
|
||||
// }
|
||||
|
||||
trait Eat {}
|
||||
impl Eat for fn() {}
|
||||
impl<T> Eat for fn(T) {}
|
||||
impl<T, K> Eat for fn(T, K) {}
|
||||
|
||||
mod other {
|
||||
use super::blah;
|
||||
fn test2() {
|
||||
// rsx!{
|
||||
// div {
|
||||
// Ele {
|
||||
// a: 10,
|
||||
// b: "asd"
|
||||
// c: impl Fn() -> ()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// becomes
|
||||
|
||||
// const reorder: fn(_, _) = |a, b| {};
|
||||
// blah::META;
|
||||
// let a = 10;
|
||||
// let b = "asd";
|
||||
// let g = [10, 10.0];
|
||||
// let c = g.a;
|
||||
|
||||
// blah(10, "asd");
|
||||
}
|
||||
}
|
||||
|
||||
struct Inner<'a> {
|
||||
a: String,
|
||||
b: i32,
|
||||
c: &'a str,
|
||||
}
|
||||
|
||||
struct Custom<'a, P: 'a> {
|
||||
inner: &'a P,
|
||||
// inner: *const (),
|
||||
_p: std::marker::PhantomData<&'a P>,
|
||||
}
|
||||
|
||||
impl<'a, P> Custom<'a, P> {
|
||||
fn props(&self) -> &P {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
// impl<P> Deref for Custom<P> {
|
||||
// type Target = Inner;
|
||||
|
||||
// fn deref(&self) -> &Self::Target {
|
||||
// unsafe { &*self.inner }
|
||||
// }
|
||||
// }
|
||||
|
||||
fn test2<'a>(a: Custom<'a, Inner<'a>>) -> VNode {
|
||||
let r = a.inner;
|
||||
|
||||
todo!()
|
||||
// let g = a.props();
|
||||
// todo!()
|
||||
// let g = &a.a;
|
||||
}
|
||||
|
||||
fn is_comp() {}
|
||||
}
|
||||
|
||||
mod style {}
|
||||
+28
-20
@@ -201,11 +201,13 @@ impl<'a> DiffMachine<'a> {
|
||||
todo!("Suspended components not currently available")
|
||||
}
|
||||
|
||||
// (VNode::Fragment(_), VNode::Fragment(_)) => {
|
||||
// todo!("Fragments not currently supported in diffing")
|
||||
// }
|
||||
// Fragments are special
|
||||
(VNode::Fragment(_), _) | (_, VNode::Fragment(_)) => {
|
||||
// we actually have to remove a bunch of nodes
|
||||
(VNode::Fragment(_), _) => {
|
||||
todo!("Fragments not currently supported in diffing")
|
||||
}
|
||||
|
||||
(_, VNode::Fragment(_)) => {
|
||||
todo!("Fragments not currently supported in diffing")
|
||||
}
|
||||
}
|
||||
@@ -227,7 +229,7 @@ impl<'a> DiffMachine<'a> {
|
||||
self.change_list.create_text_node(text);
|
||||
}
|
||||
VNode::Element(&VElement {
|
||||
key: _,
|
||||
key,
|
||||
tag_name,
|
||||
listeners,
|
||||
attributes,
|
||||
@@ -266,7 +268,12 @@ impl<'a> DiffMachine<'a> {
|
||||
|
||||
for child in children {
|
||||
self.create(child);
|
||||
self.change_list.append_child();
|
||||
if let VNode::Fragment(_) = child {
|
||||
// do nothing
|
||||
// fragments append themselves
|
||||
} else {
|
||||
self.change_list.append_child();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,22 +291,23 @@ impl<'a> DiffMachine<'a> {
|
||||
// those references are stable, even if the component arena moves around in memory, thanks to the bump arenas.
|
||||
// However, there is no way to convey this to rust, so we need to use unsafe to pierce through the lifetime.
|
||||
|
||||
let parent_idx = self.cur_idx;
|
||||
|
||||
// Insert a new scope into our component list
|
||||
let idx = self
|
||||
.components
|
||||
.with(|components| {
|
||||
components.insert_with(|new_idx| {
|
||||
let cur_idx = self.cur_idx;
|
||||
let cur_scope = self.components.try_get(cur_idx).unwrap();
|
||||
let height = cur_scope.height + 1;
|
||||
let parent_scope = self.components.try_get(parent_idx).unwrap();
|
||||
let height = parent_scope.height + 1;
|
||||
Scope::new(
|
||||
caller,
|
||||
new_idx,
|
||||
Some(cur_idx),
|
||||
Some(parent_idx),
|
||||
height,
|
||||
self.event_queue.new_channel(height, new_idx),
|
||||
self.components.clone(),
|
||||
&[],
|
||||
component.children,
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -323,24 +331,24 @@ impl<'a> DiffMachine<'a> {
|
||||
// Run the scope for one iteration to initialize it
|
||||
new_component.run_scope().unwrap();
|
||||
|
||||
// // Navigate the diff machine to the right point in the output dom
|
||||
// self.change_list.load_known_root(id);
|
||||
// let root_id = component.stable_addr
|
||||
|
||||
// And then run the diff algorithm
|
||||
self.diff_node(new_component.old_frame(), new_component.next_frame());
|
||||
|
||||
// Finally, insert this node as a seen node.
|
||||
self.seen_nodes.insert(idx);
|
||||
}
|
||||
VNode::Suspended => {
|
||||
todo!("Creation of VNode::Suspended not yet supported")
|
||||
}
|
||||
|
||||
// we go the the "known root" but only operate on a sibling basis
|
||||
VNode::Fragment(frag) => {
|
||||
//
|
||||
todo!("Cannot current create fragments")
|
||||
// create the children directly in the space
|
||||
for child in frag.children {
|
||||
self.create(child);
|
||||
self.change_list.append_child();
|
||||
}
|
||||
}
|
||||
|
||||
VNode::Suspended => {
|
||||
todo!("Creation of VNode::Suspended not yet supported")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,8 +87,6 @@ pub mod builder {
|
||||
pub use super::nodebuilder::*;
|
||||
}
|
||||
|
||||
pub mod support;
|
||||
|
||||
// types used internally that are important
|
||||
pub(crate) mod innerlude {
|
||||
pub use crate::component::*;
|
||||
@@ -122,14 +120,12 @@ pub mod prelude {
|
||||
|
||||
pub use crate::nodebuilder::LazyNodes;
|
||||
|
||||
pub use crate::nodebuilder::ChildrenList;
|
||||
pub use crate::virtual_dom::NodeCtx;
|
||||
// pub use nodes::iterables::IterableNodes;
|
||||
/// This type alias is an internal way of abstracting over the static functions that represent components.
|
||||
pub use crate::innerlude::FC;
|
||||
|
||||
// TODO @Jon, fix this
|
||||
// hack the VNode type until VirtualNode is fixed in the macro crate
|
||||
|
||||
// expose our bumpalo type
|
||||
pub use bumpalo;
|
||||
pub use bumpalo::Bump;
|
||||
@@ -141,19 +137,9 @@ pub mod prelude {
|
||||
|
||||
pub use dioxus_core_macro::{format_args_f, html, rsx, Props};
|
||||
|
||||
pub use crate::component::ScopeIdx;
|
||||
pub use crate::diff::DiffMachine;
|
||||
pub use crate::virtual_dom::ScopeIdx;
|
||||
|
||||
pub use crate::debug_renderer::DebugRenderer;
|
||||
pub use crate::dioxus_main;
|
||||
pub use crate::hooks::*;
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! dioxus_main {
|
||||
($i:ident) => {
|
||||
fn main() {
|
||||
todo!("this macro is a placeholder for launching a dioxus app on different platforms. \nYou probably don't want to use this, but it's okay for small apps.")
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
//! Helpers for building virtual DOM VNodes.
|
||||
|
||||
use std::{any::Any, borrow::BorrowMut, intrinsics::transmute, u128};
|
||||
use std::{any::Any, borrow::BorrowMut, fmt::Arguments, intrinsics::transmute, u128};
|
||||
|
||||
use crate::{
|
||||
events::VirtualEvent,
|
||||
innerlude::{Properties, VComponent, FC},
|
||||
nodes::{Attribute, Listener, NodeKey, VNode},
|
||||
prelude::VElement,
|
||||
prelude::{VElement, VFragment},
|
||||
virtual_dom::NodeCtx,
|
||||
};
|
||||
|
||||
@@ -269,6 +269,20 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn key2(mut self, args: Arguments) -> Self {
|
||||
let key = match args.as_str() {
|
||||
Some(static_str) => static_str,
|
||||
None => {
|
||||
use bumpalo::core_alloc::fmt::Write;
|
||||
let mut s = bumpalo::collections::String::new_in(self.ctx.bump());
|
||||
s.write_fmt(args).unwrap();
|
||||
s.into_bump_str()
|
||||
}
|
||||
};
|
||||
self.key = NodeKey(Some(key));
|
||||
self
|
||||
}
|
||||
|
||||
/// Create the virtual DOM VNode described by this builder.
|
||||
///
|
||||
/// # Example
|
||||
@@ -655,14 +669,49 @@ pub fn virtual_child<'a, T: Properties + 'a>(
|
||||
f: FC<T>,
|
||||
props: T,
|
||||
key: Option<&'a str>, // key: NodeKey<'a>,
|
||||
children: &'a [VNode<'a>],
|
||||
) -> VNode<'a> {
|
||||
// currently concerned about if props have a custom drop implementation
|
||||
// might override it with the props macro
|
||||
// todo!()
|
||||
VNode::Component(
|
||||
ctx.bump()
|
||||
.alloc(crate::nodes::VComponent::new(ctx.bump(), f, props, key)),
|
||||
.alloc(crate::nodes::VComponent::new(ctx, f, props, key, children)),
|
||||
// ctx.bump()
|
||||
// .alloc(crate::nodes::VComponent::new(f, props, key)),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn vfragment<'a>(
|
||||
ctx: &NodeCtx<'a>,
|
||||
key: Option<&'a str>, // key: NodeKey<'a>,
|
||||
children: &'a [VNode<'a>],
|
||||
) -> VNode<'a> {
|
||||
VNode::Fragment(ctx.bump().alloc(VFragment::new(key, children)))
|
||||
}
|
||||
|
||||
pub struct ChildrenList<'a, 'b> {
|
||||
ctx: &'b NodeCtx<'a>,
|
||||
children: bumpalo::collections::Vec<'a, VNode<'a>>,
|
||||
}
|
||||
|
||||
impl<'a, 'b> ChildrenList<'a, 'b> {
|
||||
pub fn new(ctx: &'b NodeCtx<'a>) -> Self {
|
||||
Self {
|
||||
ctx,
|
||||
children: bumpalo::collections::Vec::new_in(ctx.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.ctx);
|
||||
self.children.push(child);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn finish(self) -> &'a [VNode<'a>] {
|
||||
self.children.into_bump_slice()
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ use crate::{
|
||||
events::VirtualEvent,
|
||||
innerlude::{Context, Properties, Scope, ScopeIdx, FC},
|
||||
nodebuilder::text3,
|
||||
virtual_dom::NodeCtx,
|
||||
// support::NodeCtx,
|
||||
};
|
||||
use bumpalo::Bump;
|
||||
use std::{
|
||||
@@ -238,7 +240,6 @@ pub struct VComponent<'src> {
|
||||
|
||||
// a pointer to the raw fn typ
|
||||
pub user_fc: *const (),
|
||||
_p: PhantomData<&'src ()>,
|
||||
}
|
||||
|
||||
impl<'a> VComponent<'a> {
|
||||
@@ -249,14 +250,17 @@ impl<'a> VComponent<'a> {
|
||||
// we want them to borrow references... maybe force implementing a "to_static_unsafe" trait
|
||||
|
||||
pub fn new<P: Properties + 'a>(
|
||||
bump: &'a Bump,
|
||||
// bump: &'a Bump,
|
||||
ctx: &NodeCtx<'a>,
|
||||
component: FC<P>,
|
||||
// props: bumpalo::boxed::Box<'a, P>,
|
||||
props: P,
|
||||
key: Option<&'a str>,
|
||||
children: &'a [VNode<'a>],
|
||||
) -> Self {
|
||||
// pub fn new<P: Properties + 'a>(component: FC<P>, props: P, key: Option<&'a str>) -> Self {
|
||||
// let bad_props = unsafe { transmogrify(props) };
|
||||
let bump = ctx.bump();
|
||||
let caller_ref = component as *const ();
|
||||
let props = bump.alloc(props);
|
||||
|
||||
@@ -319,8 +323,7 @@ impl<'a> VComponent<'a> {
|
||||
user_fc: caller_ref,
|
||||
comparator,
|
||||
raw_props,
|
||||
_p: PhantomData,
|
||||
children: &[],
|
||||
children,
|
||||
caller,
|
||||
stable_addr: RefCell::new(None),
|
||||
}
|
||||
@@ -355,3 +358,14 @@ pub struct VFragment<'src> {
|
||||
pub key: NodeKey<'src>,
|
||||
pub children: &'src [VNode<'src>],
|
||||
}
|
||||
|
||||
impl<'a> VFragment<'a> {
|
||||
pub fn new(key: Option<&'a str>, children: &'a [VNode<'a>]) -> Self {
|
||||
let key = match key {
|
||||
Some(key) => NodeKey::new(key),
|
||||
None => NodeKey(None),
|
||||
};
|
||||
|
||||
Self { key, children }
|
||||
}
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
use crate::{arena::ScopeArena, innerlude::*};
|
||||
use bumpalo::Bump;
|
||||
use generational_arena::Arena;
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
cell::RefCell,
|
||||
collections::{HashMap, HashSet, VecDeque},
|
||||
fmt::Debug,
|
||||
future::Future,
|
||||
ops::Deref,
|
||||
pin::Pin,
|
||||
rc::{Rc, Weak},
|
||||
};
|
||||
// We actually allocate the properties for components in their parent's properties
|
||||
// We then expose a handle to use those props for render in the form of "OpaqueComponent"
|
||||
pub(crate) type OpaqueComponent<'e> = dyn Fn(&'e Scope) -> VNode<'e> + 'e;
|
||||
// pub(crate) type OpaqueComponent<'e> = dyn for<'b> Fn(&'b Scope) -> VNode<'b> + 'e;
|
||||
|
||||
#[derive(PartialEq, Debug, Clone, Default)]
|
||||
pub(crate) struct EventQueue(pub Rc<RefCell<Vec<HeightMarker>>>);
|
||||
|
||||
impl EventQueue {
|
||||
pub fn new_channel(&self, height: u32, idx: ScopeIdx) -> Rc<dyn Fn()> {
|
||||
let inner = self.clone();
|
||||
let marker = HeightMarker { height, idx };
|
||||
Rc::new(move || inner.0.as_ref().borrow_mut().push(marker))
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper type that lets scopes be ordered by their height
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) struct HeightMarker {
|
||||
pub idx: ScopeIdx,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
impl Ord for HeightMarker {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.height.cmp(&other.height)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for HeightMarker {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
// NodeCtx 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)]
|
||||
pub struct NodeCtx<'a> {
|
||||
pub scope_ref: &'a Scope,
|
||||
pub listener_id: RefCell<usize>,
|
||||
}
|
||||
|
||||
impl<'a> NodeCtx<'a> {
|
||||
pub fn bump(&self) -> &'a Bump {
|
||||
&self.scope_ref.cur_frame().bump
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for NodeCtx<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Hash)]
|
||||
pub struct ContextId {
|
||||
// Which component is the scope in
|
||||
original: ScopeIdx,
|
||||
|
||||
// What's the height of the scope
|
||||
height: u32,
|
||||
|
||||
// Which scope is it (in order)
|
||||
id: u32,
|
||||
}
|
||||
|
||||
pub struct ActiveFrame {
|
||||
// We use a "generation" for users of contents in the bump frames to ensure their data isn't broken
|
||||
pub generation: RefCell<usize>,
|
||||
|
||||
// The double-buffering situation that we will use
|
||||
pub frames: [BumpFrame; 2],
|
||||
}
|
||||
|
||||
pub struct BumpFrame {
|
||||
pub bump: Bump,
|
||||
pub head_node: VNode<'static>,
|
||||
}
|
||||
|
||||
impl ActiveFrame {
|
||||
pub fn new() -> Self {
|
||||
Self::from_frames(
|
||||
BumpFrame {
|
||||
bump: Bump::new(),
|
||||
head_node: VNode::text(""),
|
||||
},
|
||||
BumpFrame {
|
||||
bump: Bump::new(),
|
||||
head_node: VNode::text(""),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn from_frames(a: BumpFrame, b: BumpFrame) -> Self {
|
||||
Self {
|
||||
generation: 0.into(),
|
||||
frames: [a, b],
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn cur_frame(&self) -> &BumpFrame {
|
||||
match *self.generation.borrow() & 1 == 0 {
|
||||
true => &self.frames[0],
|
||||
false => &self.frames[1],
|
||||
}
|
||||
}
|
||||
pub(crate) fn cur_frame_mut(&mut self) -> &mut BumpFrame {
|
||||
match *self.generation.borrow() & 1 == 0 {
|
||||
true => &mut self.frames[0],
|
||||
false => &mut self.frames[1],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_head_node<'b>(&'b self) -> &'b VNode<'b> {
|
||||
let raw_node = match *self.generation.borrow() & 1 == 0 {
|
||||
true => &self.frames[0],
|
||||
false => &self.frames[1],
|
||||
};
|
||||
|
||||
// Give out our self-referential item with our own borrowed lifetime
|
||||
unsafe {
|
||||
let unsafe_head = &raw_node.head_node;
|
||||
let safe_node = std::mem::transmute::<&VNode<'static>, &VNode<'b>>(unsafe_head);
|
||||
safe_node
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prev_head_node<'b>(&'b self) -> &'b VNode<'b> {
|
||||
let raw_node = match *self.generation.borrow() & 1 != 0 {
|
||||
true => &self.frames[0],
|
||||
false => &self.frames[1],
|
||||
};
|
||||
|
||||
// Give out our self-referential item with our own borrowed lifetime
|
||||
unsafe {
|
||||
let unsafe_head = &raw_node.head_node;
|
||||
let safe_node = std::mem::transmute::<&VNode<'static>, &VNode<'b>>(unsafe_head);
|
||||
safe_node
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn next(&mut self) -> &mut BumpFrame {
|
||||
*self.generation.borrow_mut() += 1;
|
||||
|
||||
if *self.generation.borrow() % 2 == 0 {
|
||||
&mut self.frames[0]
|
||||
} else {
|
||||
&mut self.frames[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ use std::{
|
||||
pin::Pin,
|
||||
rc::{Rc, Weak},
|
||||
};
|
||||
pub type ScopeIdx = generational_arena::Index;
|
||||
|
||||
/// An integrated virtual node system that progresses events and diffs UI trees.
|
||||
/// Differences are converted into patches which a renderer can use to draw the UI.
|
||||
@@ -420,8 +421,10 @@ impl Scope {
|
||||
>(caller)
|
||||
};
|
||||
|
||||
let child_nodes = unsafe { std::mem::transmute(child_nodes) };
|
||||
|
||||
Self {
|
||||
child_nodes: &[],
|
||||
child_nodes: child_nodes,
|
||||
caller,
|
||||
parent,
|
||||
arena_idx,
|
||||
|
||||
Reference in new issue
Block a user