Feat: more cleanup

This commit is contained in:
Jonathan Kelley committed 2021-03-04 12:03:22 -05:00
1 parent cf16090838
commit 5a9155b059
17 files changed
+156 -259

No files matched your search

+2
View File
@@ -62,6 +62,8 @@ pub fn build(config: &Config, _build_config: &BuildConfig) -> Result<()> {
let mut child = cmd.spawn()?;
let _err_code = child.wait()?;
info!("Build complete!");
// [2] Establish the output directory structure
let bindgen_outdir = out_dir.join("wasm");
+8 -1
View File
@@ -1,4 +1,3 @@
use argh::FromArgs;
#[derive(FromArgs, PartialEq, Debug)]
@@ -43,6 +42,10 @@ pub struct BuildOptions {
/// an example in the crate
#[argh(option)]
pub example: Option<String>,
/// develop in release mode
#[argh(switch, short = 'r')]
pub release: bool,
}
/// 🛠 Start a development server
@@ -52,4 +55,8 @@ pub struct DevelopOptions {
/// an example in the crate
#[argh(option)]
pub example: Option<String>,
/// develop in release mode
#[argh(switch, short = 'r')]
pub release: bool,
}
+8 -3
View File
@@ -2,7 +2,6 @@ use crate::{
cli::{BuildOptions, DevelopOptions},
error::Result,
};
// use log::{info, warn};
use std::{io::Write, path::PathBuf, process::Command};
#[derive(Debug, Clone)]
@@ -70,10 +69,16 @@ impl Config {
self
}
pub fn with_release(&mut self, release: bool) -> &mut Self {
self.release = release;
self
}
pub fn with_build_options(&mut self, options: &BuildOptions) {
if let Some(name) = &options.example {
self.as_example(name.clone());
}
self.release = options.release;
self.out_dir = options.outdir.clone().into();
}
@@ -81,7 +86,7 @@ impl Config {
if let Some(name) = &options.example {
self.as_example(name.clone());
}
let outdir = tempfile::Builder::new().tempdir().expect("").into_path();
self.out_dir = outdir;
self.release = options.release;
self.out_dir = tempfile::Builder::new().tempdir().expect("").into_path();
}
}
+1 -1
View File
@@ -57,7 +57,7 @@ async fn watch_directory(config: Config) -> Result<()> {
.watch(src_dir.join("examples"), RecursiveMode::Recursive)
.expect("Failed to watch dir");
let build_config = BuildConfig::default();
let mut build_config = BuildConfig::default();
'run: loop {
crate::builder::build(&config, &build_config)?;
+10 -24
View File
@@ -1,41 +1,30 @@
use proc_macro::TokenStream;
use quote::{quote, quote_spanned, ToTokens};
use syn::spanned::Spanned;
use syn::{
parse::{Parse, ParseStream},
Signature,
};
use syn::{
parse_macro_input, Attribute, Block, FnArg, Ident, Item, ItemFn, ReturnType, Type, Visibility,
};
use quote::ToTokens;
use syn::parse_macro_input;
mod fc;
mod htm;
mod ifmt;
mod rsxt;
// mod styles;
/// The html! macro makes it easy for developers to write jsx-style markup in their components.
/// We aim to keep functional parity with html templates.
#[proc_macro]
pub fn html(s: TokenStream) -> TokenStream {
let html: htm::HtmlRender = match syn::parse(s) {
Ok(s) => s,
Err(e) => return e.to_compile_error().into(),
};
html.to_token_stream().into()
match syn::parse::<htm::HtmlRender>(s) {
Err(e) => e.to_compile_error().into(),
Ok(s) => s.to_token_stream().into(),
}
}
/// The html! macro makes it easy for developers to write jsx-style markup in their components.
/// We aim to keep functional parity with html templates.
#[proc_macro]
pub fn rsx(s: TokenStream) -> TokenStream {
let template: rsxt::RsxRender = match syn::parse(s) {
Ok(s) => s,
Err(e) => return e.to_compile_error().into(),
};
template.to_token_stream().into()
match syn::parse::<rsxt::RsxRender>(s) {
Err(e) => e.to_compile_error().into(),
Ok(s) => s.to_token_stream().into(),
}
}
/// Label a function or static closure as a functional component.
@@ -49,9 +38,6 @@ pub fn fc(attr: TokenStream, item: TokenStream) -> TokenStream {
function_component_impl(item)
.unwrap_or_else(|err| err.to_compile_error())
.into()
// function_component_impl(attr, item)
// let attr = parse_macro_input!(attr as FunctionComponentName);
}
#[proc_macro]
+2 -2
View File
@@ -144,9 +144,9 @@ impl ToTokens for ToToksCtx<&Element> {
fn to_tokens(&self, tokens: &mut TokenStream2) {
// todo!()
// // let ctx = self.ctx;
let name = &self.inner.name;
let name = &self.inner.name.to_string();
tokens.append_all(quote! {
dioxus::builder::ElementBuilder::new(ctx, "#name")
dioxus::builder::ElementBuilder::new(ctx, #name)
});
for attr in self.inner.attrs.iter() {
self.recurse(attr).to_tokens(tokens);
+13 -15
View File
@@ -2,7 +2,6 @@ use crate::nodes::VNode;
use crate::prelude::*;
use bumpalo::Bump;
use hooks::Hook;
use log::info;
use std::{
any::TypeId, borrow::Borrow, cell::RefCell, future::Future, marker::PhantomData, ops::Deref,
rc::Rc, sync::atomic::AtomicUsize,
@@ -56,6 +55,8 @@ impl<'a> Context<'a> {
todo!("Children API not yet implemented for component Context")
}
pub fn callback(&self, _f: impl Fn(()) + 'a) {}
/// Create a subscription that schedules a future render for the reference component
pub fn schedule_update(&self) -> impl Fn() -> () {
// log::debug!()
@@ -63,6 +64,16 @@ impl<'a> Context<'a> {
|| {}
}
/// Create a suspended component from a future.
///
/// When the future completes, the component will be renderered
pub fn suspend(
&self,
_fut: impl Future<Output = impl FnOnce(&'a NodeCtx<'a>) -> VNode<'a>>,
) -> VNode<'a> {
todo!()
}
/// Take a lazy VNode structure and actually build it with the context of the VDom's efficient VNode allocator.
///
/// This function consumes the context and absorb the lifetime, so these VNodes *must* be returned.
@@ -84,25 +95,12 @@ impl<'a> Context<'a> {
idx: 0.into(),
scope: self.scope,
};
// todo!();
let safe_nodes = lazy_nodes(&ctx);
let safe_nodes = lazy_nodes(&ctx);
let unsafe_nodes = unsafe { std::mem::transmute::<VNode<'a>, VNode<'static>>(safe_nodes) };
self.final_nodes.deref().borrow_mut().replace(unsafe_nodes);
DomTree {}
}
pub fn callback(&self, _f: impl Fn(()) + 'a) {}
/// Create a suspended component from a future.
///
/// When the future completes, the component will be renderered
pub fn suspend(
&self,
_fut: impl Future<Output = impl FnOnce(&'a NodeCtx<'a>) -> VNode<'a>>,
) -> VNode<'a> {
todo!()
}
}
// NodeCtx is used to build VNodes in the component's memory space.
+10 -27
View File
@@ -58,13 +58,11 @@ pub struct DiffMachine<'a> {
impl<'a> DiffMachine<'a> {
pub fn new(bump: &'a Bump) -> Self {
// log::debug!("starting diff machine");
Self {
change_list: EditMachine::new(bump),
immediate_queue: Vec::new(),
diffed: FxHashSet::default(),
need_to_diff: FxHashSet::default(),
// current_idx: None,
}
}
@@ -72,19 +70,13 @@ impl<'a> DiffMachine<'a> {
self.change_list.emitter
}
pub fn diff_node(
&mut self,
old: &VNode<'a>,
new: &VNode<'a>,
// scope: Option<generational_arena::Index>,
) {
pub fn diff_node(&mut self, old: &VNode<'a>, new: &VNode<'a>) {
/*
For each valid case, we "commit traversal", meaning we save this current position in the tree.
Then, we diff and queue an edit event (via chagelist). s single trees - when components show up, we save that traversal and then re-enter later.
When re-entering, we reuse the EditList in DiffState
*/
match (old, new) {
// This case occurs when two text nodes are generation
(VNode::Text(VText { text: old_text }), VNode::Text(VText { text: new_text })) => {
if old_text != new_text {
self.change_list.commit_traversal();
@@ -93,12 +85,8 @@ impl<'a> DiffMachine<'a> {
}
(VNode::Text(_), VNode::Element(_)) => {
// TODO: Hook up the events properly
// todo!("Hook up events registry");
self.change_list.commit_traversal();
// diff_support::create(cached_set, self.change_list, registry, new, cached_roots);
self.create(new);
// registry.remove_subtree(&old);
self.change_list.replace_with();
}
@@ -121,30 +109,25 @@ impl<'a> DiffMachine<'a> {
self.diff_children(eold.children, enew.children);
}
(VNode::Component(_), VNode::Component(_)) => {
(VNode::Component(cold), VNode::Component(cnew)) => {
if cold.comp != cnew.comp {
// queue an event to mount this new component
return;
}
// compare props.... somehow.....
todo!("Usage of component VNode not currently supported");
}
(_, VNode::Component(_)) => {
todo!("Usage of component VNode not currently supported");
}
(VNode::Component(_), _) => {
(_, VNode::Component(_)) | (VNode::Component(_), _) => {
todo!("Usage of component VNode not currently supported");
}
(VNode::Suspended, _) | (_, VNode::Suspended) => {
// (VNode::Element(_), VNode::Suspended) => {}
// (VNode::Text(_), VNode::Suspended) => {}
// (VNode::Component(_), VNode::Suspended) => {}
// (VNode::Suspended, VNode::Element(_)) => {}
// (VNode::Suspended, VNode::Text(_)) => {}
// (VNode::Suspended, VNode::Suspended) => {}
// (VNode::Suspended, VNode::Component(_)) => {}
todo!("Suspended components not currently available")
}
}
// self.current_idx = None;
}
// Diff event listeners between `old` and `new`.
-32
View File
@@ -1,5 +1,4 @@
use thiserror::Error as ThisError;
pub type Result<T, E = Error> = std::result::Result<T, E>;
#[derive(ThisError, Debug)]
@@ -13,37 +12,6 @@ pub enum Error {
#[error("Base scope has not been mounted yet")]
NotMounted,
// #[error("Out of compute credits")]
// OutOfCredits,
// /// Used when errors need to propogate but are too unique to be typed
// #[error("{0}")]
// Unique(String),
// #[error("GraphQL error: {0}")]
// GraphQL(String),
// // TODO(haze): Remove, or make a better error. This is pretty much useless
// #[error("GraphQL response mismatch. Got {found} but expected {expected}")]
// GraphQLMisMatch {
// expected: &'static str,
// found: String,
// },
// #[error("Difference detected in SystemTime! {0}")]
// SystemTime(#[from] std::time::SystemTimeError),
// #[error("Failed to parse Integer")]
// ParseInt(#[from] std::num::ParseIntError),
// #[error("")]
// MissingAuthentication,
// #[error("Failed to create experiment run: {0}")]
// FailedToCreateExperimentRun(String),
// #[error("Could not find shared behavior with ID {0}")]
// MissingSharedBehavior(String),
#[error("I/O Error: {0}")]
IO(#[from] std::io::Error),
}
+2 -2
View File
@@ -28,8 +28,8 @@ mod use_state_def {
/// ```ignore
/// static Example: FC<()> = |ctx| {
/// let (counter, set_counter) = use_state(ctx, || 0);
/// let increment = || set_couter(counter + 1);
/// let decrement = || set_couter(counter + 1);
/// let increment = |_| set_couter(counter + 1);
/// let decrement = |_| set_couter(counter + 1);
///
/// html! {
/// <div>
+2
View File
@@ -442,6 +442,8 @@ where
self.children.push(child);
self
}
// pub fn virtual_child(mut self)
}
/// Construct a text VNode.
+44 -8
View File
@@ -296,21 +296,57 @@ mod vtext {
/// Virtual Components for custom user-defined components
/// Only supports the functional syntax
mod vcomponent {
use crate::innerlude::FC;
use std::marker::PhantomData;
use crate::innerlude::{Context, FC};
use std::{any::TypeId, marker::PhantomData};
use super::DomTree;
#[derive(Debug)]
pub struct VComponent<'src> {
_p: PhantomData<&'src ()>,
props: Box<dyn std::any::Any>,
// props: Box<dyn Properties + 'src>,
caller: *const (),
pub(crate) props: Box<dyn std::any::Any>,
pub(crate) props_type: TypeId,
pub(crate) comp: *const (),
pub(crate) caller: Caller,
}
pub struct Caller(Box<dyn Fn(Context) -> DomTree>);
impl std::fmt::Debug for Caller {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
todo!()
}
}
impl<'a> VComponent<'a> {
pub fn new<P>(caller: FC<P>, props: P) -> Self {
let _caller = caller as *const ();
let _props = Box::new(props);
// use the type parameter on props creation and move it into a portable context
// this lets us keep scope generic *and* downcast its props when we need to:
// - perform comparisons when diffing (memoization)
// -
pub fn new<P>(comp: FC<P>, props: P) -> Self {
let caller = move |ctx: Context| {
let t = comp(ctx, &props);
t
};
// let _caller = comp as *const ();
// let _props = Box::new(props);
// cast to static?
// how do we save the type of props ?
// do it in the caller function?
// something like
// the "true" entrpypoint
//
// |caller| caller.call(fn, Props {})
// fn call<P>(f, new_props) {
// let old_props = old.downcast_ref::<P>();
// if new_props == old_props {
// return;
// } else {
// // set the new props
// // call the fn
// }
// }
todo!()
// Self {
+6 -30
View File
@@ -107,7 +107,6 @@ pub enum Edit<'d> {
RemoveListener {
event: &'d str,
},
// NewListener { event: &'d str, id: usize, s: ScopeIdx },
}
pub type EditList<'src> = Vec<Edit<'src>>;
@@ -167,40 +166,17 @@ impl<'b> EditMachine<'b> {
pub fn commit_traversal(&mut self) {
if self.traversal.is_committed() {
log::debug!("Traversal already committed");
return;
}
for mv in self.traversal.commit() {
match mv {
MoveTo::Parent => {
log::debug!("emit: pop");
self.emitter.push(Edit::Pop {});
// self.emitter.pop();
}
MoveTo::Child(n) => {
log::debug!("emit: push_child({})", n);
self.emitter.push(Edit::PushChild { n });
}
MoveTo::ReverseChild(n) => {
log::debug!("emit: push_reverse_child({})", n);
self.emitter.push(Edit::PushReverseChild { n });
// self.emitter.push_reverse_child(n);
}
MoveTo::Sibling(n) => {
log::debug!("emit: pop_push_child({})", n);
self.emitter.push(Edit::PopPushChild { n });
// self.emitter.pop_push_child(n);
}
MoveTo::ReverseSibling(n) => {
log::debug!("emit: pop_push_reverse_child({})", n);
self.emitter.push(Edit::PopPushReverseChild { n });
}
MoveTo::TempChild(temp) => {
log::debug!("emit: push_temporary({})", temp);
self.emitter.push(Edit::PushTemporary { temp });
// self.emitter.push_temporary(temp);
}
MoveTo::Parent => self.emitter.push(Edit::Pop {}),
MoveTo::Child(n) => self.emitter.push(Edit::PushChild { n }),
MoveTo::ReverseChild(n) => self.emitter.push(Edit::PushReverseChild { n }),
MoveTo::Sibling(n) => self.emitter.push(Edit::PopPushChild { n }),
MoveTo::ReverseSibling(n) => self.emitter.push(Edit::PopPushReverseChild { n }),
MoveTo::TempChild(temp) => self.emitter.push(Edit::PushTemporary { temp }),
}
}
}
+31 -99
View File
@@ -227,6 +227,8 @@ impl ActiveFrame {
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);
@@ -240,6 +242,7 @@ impl ActiveFrame {
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);
@@ -250,56 +253,28 @@ impl ActiveFrame {
fn next(&mut self) -> &mut BumpFrame {
self.idx.fetch_add(1, Ordering::Relaxed);
let cur = self.idx.borrow().load(Ordering::Relaxed);
log::debug!("Next frame! {}", cur);
if cur % 2 == 0 {
log::debug!("Chosing frame 0");
&mut self.frames[0]
} else {
log::debug!("Chosing frame 1");
&mut self.frames[1]
}
// match cur % 1 {
// 0 => {
// }
// 1 => {
// }
// _ => unreachable!("mod cannot by non-zero"),
// }
}
}
// #[cfg(test)]
mod tests {
use super::*;
use crate::prelude::bumpalo;
// use crate::prelude::bumpalo::collections::string::String;
use crate::prelude::format_args_f;
use crate::prelude::*;
static ListenerTest: FC<()> = |ctx, props| {
ctx.render(move |c| {
//
builder::ElementBuilder::new(c, "div").finish()
ctx.render(html! {
<div onclick={|_| println!("Hell owlrld")}>
"hello"
</div>
})
// ctx.render(html! {
// <div onclick={|_| println!("Hell owlrld")}>
// "hello"
// </div>
// })
};
#[test]
fn check_listeners() -> Result<()> {
todo!()
// let mut scope = Scope::new::<(), ()>(ListenerTest, (), None);
// scope.run::<()>();
// let nodes = scope.new_frame();
// dbg!(nodes);
// Ok(())
}
#[test]
fn test_scope() {
let example: FC<()> = |ctx, props| {
@@ -316,7 +291,6 @@ mod tests {
let mut nodes = generational_arena::Arena::new();
nodes.insert_with(|f| {
let scope = Scope::new::<(), ()>(example, props, f, parent);
//
});
}
@@ -324,103 +298,61 @@ mod tests {
struct ExampleProps<'src> {
name: &'src String,
}
// impl<'src> Properties<'src> for ExampleProps<'src> {}
#[derive(Debug)]
struct EmptyProps<'src> {
name: &'src String,
}
// impl<'src> Properties<'src> for EmptyProps<'src> {}
use crate::{builder::*, hooks::use_ref};
fn example_fc<'a>(ctx: Context<'a>, props: &'a EmptyProps) -> DomTree {
// fn example_fc<'a>(ctx: Context<'a>, props: &'a EmptyProps<'a>) -> DomTree {
let (content, _): (&'a String, _) = crate::hooks::use_state(&ctx, || "abcd".to_string());
// let (content, _): (&'a String, _) = crate::hooks::use_state(&ctx, || "abcd".to_string());
// let (text, set_val) = crate::hooks::use_state(&ctx, || "abcd".to_string());
let childprops: ExampleProps<'a> = ExampleProps { name: content };
// let childprops: ExampleProps<'a> = ExampleProps { name: content };
ctx.render(move |ctx| {
todo!()
// let b = ctx.bump();
// div(b)
// .child(text(props.name))
// // .child(text(props.name))
// .child(virtual_child::<ExampleProps>(b, childprops, child_example))
// // .child(virtual_child::<ExampleProps<'a>>(b, childprops, CHILD))
// // as for<'scope> fn(Context<'_>, &'scope ExampleProps<'scope>) -> DomTree
// // |ctx, pops| todo!(),
// // .child(virtual_child::<'a>(
// // b,
// // child_example,
// // ExampleProps { name: text },
// // ))
// .finish()
ctx.render(move |c| {
builder::ElementBuilder::new(c, "div")
.child(text(props.name))
.child(virtual_child::<ExampleProps>(
c.bump,
childprops,
child_example,
))
.finish()
})
}
fn child_example<'b>(ctx: Context<'b>, props: &'b ExampleProps) -> DomTree {
ctx.render(move |ctx| {
todo!()
// div(ctx.bump())
// .child(text(props.name))
// //
// .finish()
builder::ElementBuilder::new(ctx, "div")
.child(text(props.name))
.finish()
})
}
static CHILD: FC<ExampleProps> = |ctx, props: &'_ ExampleProps| {
// todo!()
ctx.render(move |ctx| {
todo!()
// div(ctx.bump())
// .child(text(props.name))
// //
// .finish()
builder::ElementBuilder::new(ctx, "div")
.child(text(props.name))
.finish()
})
};
#[test]
fn test_borrowed_scope() {
// use crate::builder::*;
let example: FC<EmptyProps> = |ctx, props| {
// render counter
// let mut val = crate::hooks::use_ref(&ctx, || 0);
// val.modify(|f| {
// *f += 1;
// });
// dbg!(val.current());
// only needs to be valid when ran?
// can only borrow from parent?
// props are boxed in parent's scope?
// passing complex structures down to child?
// stored value
// let (text, set_val) = crate::hooks::use_state(&ctx, || "abcd".to_string());
ctx.render(move |b| {
todo!()
// div(b)
// // .child(text(props.name))
// // .child(virtual_child(b, CHILD, ExampleProps { name: val.as_str() }))
// .child(virtual_child(b, CHILD, ExampleProps { name: }))
// .finish()
builder::ElementBuilder::new(b, "div")
.child(virtual_child(
b.bump,
ExampleProps { name: props.name },
CHILD,
))
.finish()
})
};
let source_text = "abcd123".to_string();
let props = ExampleProps { name: &source_text };
// let parent = None;
// let mut scope =
// Scope::new::<EmptyProps, EmptyProps>(example, EmptyProps { name: &() }, parent);
// scope.run::<ExampleProps>();
// scope.run::<ExampleProps>();
// scope.run::<ExampleProps>();
// scope.run::<ExampleProps>();
// scope.run::<ExampleProps>();
// let nodes = scope.current_root_node();
// dbg!(nodes);
}
}
+4 -3
View File
@@ -25,11 +25,12 @@ pub struct VirtualDom {
/// Will not be ready if the dom is fresh
base_scope: ScopeIdx,
event_queue: Rc<RefCell<VecDeque<LifecycleEvent>>>,
event_queue: RefCell<VecDeque<LifecycleEvent>>,
// todo: encapsulate more state into this so we can better reuse it
diff_bump: Bump,
// Type of the original props. This is done so VirtualDom does not need to be generic.
#[doc(hidden)]
_root_prop_type: std::any::TypeId,
}
@@ -51,7 +52,7 @@ impl VirtualDom {
pub fn new_with_props<P: 'static>(root: FC<P>, root_props: P) -> Self {
let mut components = Arena::new();
let event_queue = Rc::new(RefCell::new(VecDeque::new()));
let event_queue = RefCell::new(VecDeque::new());
// Create a reference to the component in the arena
// Note: we are essentially running the "Mount" lifecycle event manually while the vdom doesnt yet exist
@@ -212,7 +213,7 @@ impl VirtualDom {
/// Pop the top event of the internal lifecycle event queu
pub fn pop_event(&self) -> Option<LifecycleEvent> {
self.event_queue.as_ref().borrow_mut().pop_front()
self.event_queue.borrow_mut().pop_front()
}
/// With access to the virtual dom, schedule an update to the Root component's props.
+8 -7
View File
@@ -8,15 +8,14 @@ use dioxus_web::WebsysRenderer;
// static IMG: ImgAsset = dioxus_asset!("");
fn main() {
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
console_error_panic_hook::set_once();
// wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
// console_error_panic_hook::set_once();
wasm_bindgen_futures::spawn_local(WebsysRenderer::start(Example))
}
static Example: FC<()> = |ctx, props| {
let (name, set_name) = use_state(&ctx, || "...?");
let handler = move |_| set_name("jill");
ctx.render(rsx! {
div {
@@ -36,12 +35,14 @@ static Example: FC<()> = |ctx, props| {
}
button {
class: "inline-block py-4 px-8 mr-6 leading-none text-white bg-indigo-600 hover:bg-indigo-900 font-semibold rounded shadow"
onfocus: {handler}
onmouseover: move |_| {
set_name("jill");
}
onmouseover: move |_| set_name("jill")
"Jill!"
}
button {
class: "inline-block py-4 px-8 mr-6 leading-none text-white bg-indigo-600 hover:bg-indigo-900 font-semibold rounded shadow"
onmouseover: move |e| set_name("....")
"Reset!"
}
}
})
};
+5 -5
View File
@@ -76,27 +76,27 @@ impl WebsysRenderer {
// todo: initialize the event registry properly on the root
self.internal_dom.rebuild()?.iter().for_each(|edit| {
log::debug!("patching with {:?}", edit);
// log::debug!("patching with {:?}", edit);
patch_machine.handle_edit(edit);
});
log::debug!("patch stack size {:?}", patch_machine.stack);
// log::debug!("patch stack size {:?}", patch_machine.stack);
// Event loop waits for the receiver to finish up
// TODO! Connect the sender to the virtual dom's suspense system
// Suspense is basically an external event that can force renders to specific nodes
while let Some(event) = receiver.next().await {
log::debug!("patch stack size before {:#?}", patch_machine.stack);
// log::debug!("patch stack size before {:#?}", patch_machine.stack);
// patch_machine.reset();
// patch_machine.stack.push(root_node.clone());
self.internal_dom
.progress_with_event(event)?
.iter()
.for_each(|edit| {
log::debug!("edit stream {:?}", edit);
// log::debug!("edit stream {:?}", edit);
patch_machine.handle_edit(edit);
});
log::debug!("patch stack size after {:#?}", patch_machine.stack);
// log::debug!("patch stack size after {:#?}", patch_machine.stack);
patch_machine.reset();
// our root node reference gets invalidated
// not sure why