Feat: major overhaul to diffing, using a "diffing machine" now

This commit is contained in:
Jonathan Kelley committed 2021-02-14 18:03:16 -05:00
1 parent 4c291a0efd
commit 4dfdf91236
10 files changed
+822 -780

No files matched your search

+37 -9
View File
@@ -1,11 +1,11 @@
use crate::context::hooks::Hook;
use crate::innerlude::*;
use crate::nodes::VNode;
use crate::{context::hooks::Hook, diff::diff};
use bumpalo::Bump;
use generational_arena::Index;
use std::{
any::TypeId, borrow::Borrow, cell::RefCell, future::Future, marker::PhantomData,
sync::atomic::AtomicUsize,
sync::atomic::AtomicUsize, todo,
};
/// Every component in Dioxus is represented by a `Scope`.
@@ -29,9 +29,13 @@ pub struct Scope {
pub frames: [Bump; 2],
// somehow build this vnode with a lifetime tied to self
pub cur_node: *mut VNode<'static>,
// This root node has "static" lifetime, but it's really not static.
// It's goverened by the oldest of the two frames and is switched every time a new render occurs
// Use this node as if it were static is unsafe, and needs to be fixed with ourborous or owning ref
// ! do not copy this reference are things WILL break !
pub root_node: *mut VNode<'static>,
pub active_frame: u8,
pub active_frame: ActiveFrame,
// IE Which listeners need to be woken up?
pub listeners: Vec<Box<dyn Fn()>>,
@@ -41,6 +45,20 @@ pub struct Scope {
pub caller: *const i32,
}
pub enum ActiveFrame {
First,
Second,
}
impl ActiveFrame {
fn next(&mut self) {
match self {
ActiveFrame::First => *self = ActiveFrame::Second,
ActiveFrame::Second => *self = ActiveFrame::First,
}
}
}
impl Scope {
// create a new scope from a function
pub(crate) fn new<T: 'static>(f: FC<T>, parent: Option<Index>) -> Self {
@@ -49,15 +67,19 @@ impl Scope {
let hook_arena = typed_arena::Arena::new();
let hooks = RefCell::new(Vec::new());
// Capture the caller
let caller = f as *const i32;
// Create the two buffers the componetn will render into
// There will always be an "old" and "new"
let frames = [Bump::new(), Bump::new()];
let listeners = Vec::new();
let active_frame = 1;
let active_frame = ActiveFrame::First;
let new = frames[0].alloc(VNode::Text(VText::new("")));
let cur_node = new as *mut _;
Self {
@@ -69,7 +91,7 @@ impl Scope {
listeners,
parent,
frames,
cur_node,
root_node: cur_node,
}
}
@@ -78,7 +100,12 @@ impl Scope {
///
/// Props is ?Sized because we borrow the props and don't need to know the size. P (sized) is used as a marker (unsized)
pub(crate) fn run<'a, P: Properties + ?Sized>(&self, props: &'a P) {
let bump = &self.frames[0];
let bump = match self.active_frame {
// If the active frame is the first, then we need to bump into the second
ActiveFrame::First => &self.frames[1],
// If the active frame is the second, then we need to bump into the first
ActiveFrame::Second => &self.frames[0],
}; // n.b, there might be a better way of doing this active frame stuff - perhaps swapping
let ctx = Context {
scope: &*self,
@@ -102,13 +129,14 @@ impl Scope {
*/
let caller = unsafe { std::mem::transmute::<*const i32, FC<P>>(self.caller) };
let new_nodes = caller(ctx, props);
let old_nodes: &mut VNode<'static> = unsafe { &mut *self.cur_node };
let old_nodes: &mut VNode<'static> = unsafe { &mut *self.root_node };
// TODO: Iterate through the new nodes
// move any listeners into ourself
// perform the diff, dumping into the mutable change list
// this doesnt perform any "diff compression" where an event and a re-render
crate::diff::diff(old_nodes, &new_nodes);
// crate::diff::diff(old_nodes, &new_nodes);
todo!()
}
}