2022-11-02 01:42:29 +00:00
|
|
|
use crate::any_props::VComponentProps;
|
|
|
|
use crate::arena::ElementPath;
|
2022-11-03 08:38:18 +00:00
|
|
|
use crate::component::Component;
|
2022-11-02 01:42:29 +00:00
|
|
|
use crate::diff::DirtyScope;
|
2022-11-04 03:56:31 +00:00
|
|
|
use crate::factory::RenderReturn;
|
2022-11-06 08:48:34 +00:00
|
|
|
use crate::innerlude::{Scheduler, SchedulerMsg};
|
2022-11-02 01:42:29 +00:00
|
|
|
use crate::mutations::Mutation;
|
|
|
|
use crate::nodes::{Template, TemplateId};
|
2022-11-06 08:48:34 +00:00
|
|
|
|
2022-11-02 01:42:29 +00:00
|
|
|
use crate::{
|
|
|
|
arena::ElementId,
|
|
|
|
scopes::{ScopeId, ScopeState},
|
|
|
|
};
|
2022-11-06 08:48:34 +00:00
|
|
|
use crate::{scheduler, Element, Scope};
|
2022-11-02 01:42:29 +00:00
|
|
|
use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
2022-11-08 06:55:22 +00:00
|
|
|
use scheduler::{SuspenseBoundary, SuspenseContext};
|
2022-11-02 01:42:29 +00:00
|
|
|
use slab::Slab;
|
2022-11-08 06:55:22 +00:00
|
|
|
use std::cell::RefCell;
|
2022-11-02 01:42:29 +00:00
|
|
|
use std::collections::{BTreeSet, HashMap};
|
2022-11-08 06:55:22 +00:00
|
|
|
use std::rc::Rc;
|
2022-11-02 01:42:29 +00:00
|
|
|
|
|
|
|
pub struct VirtualDom {
|
2022-11-02 08:00:37 +00:00
|
|
|
pub(crate) templates: HashMap<TemplateId, Template<'static>>,
|
2022-11-02 01:42:29 +00:00
|
|
|
pub(crate) elements: Slab<ElementPath>,
|
|
|
|
pub(crate) scopes: Slab<ScopeState>,
|
|
|
|
pub(crate) scope_stack: Vec<ScopeId>,
|
|
|
|
pub(crate) element_stack: Vec<ElementId>,
|
|
|
|
pub(crate) dirty_scopes: BTreeSet<DirtyScope>,
|
2022-11-06 08:48:34 +00:00
|
|
|
pub(crate) scheduler: Scheduler,
|
2022-11-02 01:42:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl VirtualDom {
|
2022-11-04 00:34:42 +00:00
|
|
|
pub fn new(app: fn(Scope) -> Element) -> Self {
|
2022-11-06 08:48:34 +00:00
|
|
|
let scheduler = Scheduler::new();
|
2022-11-02 01:42:29 +00:00
|
|
|
|
|
|
|
let mut res = Self {
|
|
|
|
templates: Default::default(),
|
|
|
|
scopes: Slab::default(),
|
|
|
|
elements: Default::default(),
|
|
|
|
scope_stack: Vec::new(),
|
|
|
|
element_stack: vec![ElementId(0)],
|
|
|
|
dirty_scopes: BTreeSet::new(),
|
2022-11-06 08:48:34 +00:00
|
|
|
scheduler,
|
2022-11-02 01:42:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let props = Box::into_raw(Box::new(VComponentProps::new_empty(app)));
|
2022-11-04 00:34:42 +00:00
|
|
|
let props: *mut VComponentProps<(), ()> = unsafe { std::mem::transmute(props) };
|
2022-11-02 01:42:29 +00:00
|
|
|
|
|
|
|
let root = res.new_scope(props);
|
|
|
|
|
2022-11-04 05:30:26 +00:00
|
|
|
// the root component is always a suspense boundary for any async children
|
2022-11-08 06:55:22 +00:00
|
|
|
res.scopes[root.0].provide_context(Rc::new(RefCell::new(SuspenseBoundary::new(root))));
|
2022-11-04 05:30:26 +00:00
|
|
|
|
2022-11-02 01:42:29 +00:00
|
|
|
assert_eq!(root, ScopeId(0));
|
|
|
|
|
|
|
|
res
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Render the virtualdom, without processing any suspense.
|
|
|
|
pub fn rebuild<'a>(&'a mut self, mutations: &mut Vec<Mutation<'a>>) {
|
2022-11-04 03:56:31 +00:00
|
|
|
let root_node: &RenderReturn = self.run_scope(ScopeId(0));
|
|
|
|
let root_node: &RenderReturn = unsafe { std::mem::transmute(root_node) };
|
|
|
|
match root_node {
|
|
|
|
RenderReturn::Sync(Some(node)) => {
|
|
|
|
self.scope_stack.push(ScopeId(0));
|
|
|
|
self.create(mutations, node);
|
|
|
|
self.scope_stack.pop();
|
|
|
|
}
|
2022-11-06 08:48:34 +00:00
|
|
|
RenderReturn::Sync(None) => {
|
|
|
|
//
|
|
|
|
}
|
2022-11-04 03:56:31 +00:00
|
|
|
RenderReturn::Async(_) => unreachable!(),
|
|
|
|
}
|
2022-11-02 01:42:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Render what you can given the timeline and then move on
|
|
|
|
pub async fn render_with_deadline<'a>(
|
|
|
|
&'a mut self,
|
|
|
|
future: impl std::future::Future<Output = ()>,
|
|
|
|
mutations: &mut Vec<Mutation<'a>>,
|
|
|
|
) {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Whenever the future is canceled, the VirtualDom will be
|
|
|
|
pub async fn render<'a>(&'a mut self, mutations: &mut Vec<Mutation<'a>>) {
|
|
|
|
//
|
|
|
|
}
|
|
|
|
|
2022-11-02 08:00:37 +00:00
|
|
|
pub fn get_scope(&self, id: ScopeId) -> Option<&ScopeState> {
|
|
|
|
self.scopes.get(id.0)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn base_scope(&self) -> &ScopeState {
|
|
|
|
self.scopes.get(0).unwrap()
|
|
|
|
}
|
2022-11-02 01:42:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for VirtualDom {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
// self.drop_scope(ScopeId(0));
|
|
|
|
}
|
|
|
|
}
|