From 5a9155b059acc1fb3c8b8accbeca3701ce4f0ab6 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Thu, 4 Mar 2021 12:03:22 -0500 Subject: [PATCH] Feat: more cleanup --- packages/cli/src/builder.rs | 2 + packages/cli/src/cli.rs | 9 ++- packages/cli/src/config.rs | 11 ++- packages/cli/src/develop.rs | 2 +- packages/core-macro/src/lib.rs | 34 +++----- packages/core-macro/src/rsxt.rs | 4 +- packages/core/src/context.rs | 28 ++++--- packages/core/src/diff.rs | 37 +++------ packages/core/src/error.rs | 32 -------- packages/core/src/hooks.rs | 4 +- packages/core/src/nodebuilder.rs | 2 + packages/core/src/nodes.rs | 52 +++++++++++-- packages/core/src/patch.rs | 36 ++------- packages/core/src/scope.rs | 130 ++++++++----------------------- packages/core/src/virtual_dom.rs | 7 +- packages/web/examples/rsxt.rs | 15 ++-- packages/web/src/lib.rs | 10 +-- 17 files changed, 156 insertions(+), 259 deletions(-) diff --git a/packages/cli/src/builder.rs b/packages/cli/src/builder.rs index 0da93f5e8..3cecf4e35 100644 --- a/packages/cli/src/builder.rs +++ b/packages/cli/src/builder.rs @@ -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"); diff --git a/packages/cli/src/cli.rs b/packages/cli/src/cli.rs index 61b6af72c..852d4ee71 100644 --- a/packages/cli/src/cli.rs +++ b/packages/cli/src/cli.rs @@ -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, + + /// 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, + + /// develop in release mode + #[argh(switch, short = 'r')] + pub release: bool, } diff --git a/packages/cli/src/config.rs b/packages/cli/src/config.rs index 314fd57bc..02a04eaf7 100644 --- a/packages/cli/src/config.rs +++ b/packages/cli/src/config.rs @@ -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(); } } diff --git a/packages/cli/src/develop.rs b/packages/cli/src/develop.rs index 03ab6a523..4c6a853d8 100644 --- a/packages/cli/src/develop.rs +++ b/packages/cli/src/develop.rs @@ -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)?; diff --git a/packages/core-macro/src/lib.rs b/packages/core-macro/src/lib.rs index 6bf00e5db..e9b24c0be 100644 --- a/packages/core-macro/src/lib.rs +++ b/packages/core-macro/src/lib.rs @@ -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::(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::(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] diff --git a/packages/core-macro/src/rsxt.rs b/packages/core-macro/src/rsxt.rs index 6e24fa4b5..719a7828c 100644 --- a/packages/core-macro/src/rsxt.rs +++ b/packages/core-macro/src/rsxt.rs @@ -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); diff --git a/packages/core/src/context.rs b/packages/core/src/context.rs index 074f17681..184318e1d 100644 --- a/packages/core/src/context.rs +++ b/packages/core/src/context.rs @@ -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) -> 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<'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) -> VNode<'a>>, - ) -> VNode<'a> { - todo!() - } } // NodeCtx is used to build VNodes in the component's memory space. diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index 2768266b9..7710db6d1 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -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, - ) { + 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`. diff --git a/packages/core/src/error.rs b/packages/core/src/error.rs index 2de19607f..18b78a9a0 100644 --- a/packages/core/src/error.rs +++ b/packages/core/src/error.rs @@ -1,5 +1,4 @@ use thiserror::Error as ThisError; - pub type Result = std::result::Result; #[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), } diff --git a/packages/core/src/hooks.rs b/packages/core/src/hooks.rs index 4632284bc..427b22df8 100644 --- a/packages/core/src/hooks.rs +++ b/packages/core/src/hooks.rs @@ -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! { ///
diff --git a/packages/core/src/nodebuilder.rs b/packages/core/src/nodebuilder.rs index 8b6215e79..dccb1e2d6 100644 --- a/packages/core/src/nodebuilder.rs +++ b/packages/core/src/nodebuilder.rs @@ -442,6 +442,8 @@ where self.children.push(child); self } + + // pub fn virtual_child(mut self) } /// Construct a text VNode. diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs index 07e8a2669..535ebf79d 100644 --- a/packages/core/src/nodes.rs +++ b/packages/core/src/nodes.rs @@ -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, - // props: Box, - caller: *const (), + pub(crate) props: Box, + pub(crate) props_type: TypeId, + pub(crate) comp: *const (), + pub(crate) caller: Caller, + } + + pub struct Caller(Box 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

(caller: FC

, 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

(comp: FC

, 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

(f, new_props) { + // let old_props = old.downcast_ref::

(); + // if new_props == old_props { + // return; + // } else { + // // set the new props + // // call the fn + // } + // } todo!() // Self { diff --git a/packages/core/src/patch.rs b/packages/core/src/patch.rs index 3ecc72349..15cb98ca8 100644 --- a/packages/core/src/patch.rs +++ b/packages/core/src/patch.rs @@ -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>; @@ -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 }), } } } diff --git a/packages/core/src/scope.rs b/packages/core/src/scope.rs index f06fa555b..55bf18e6a 100644 --- a/packages/core/src/scope.rs +++ b/packages/core/src/scope.rs @@ -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! { +

+ "hello" +
}) - // ctx.render(html! { - //
- // "hello" - //
- // }) }; - #[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::(b, childprops, child_example)) - // // .child(virtual_child::>(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::( + 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 = |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 = |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::(example, EmptyProps { name: &() }, parent); - // scope.run::(); - // scope.run::(); - // scope.run::(); - // scope.run::(); - // scope.run::(); - // let nodes = scope.current_root_node(); - // dbg!(nodes); } } diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index 6f5cb1ad8..be62bcc0a 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -25,11 +25,12 @@ pub struct VirtualDom { /// Will not be ready if the dom is fresh base_scope: ScopeIdx, - event_queue: Rc>>, + event_queue: RefCell>, // 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(root: FC

, 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 { - 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. diff --git a/packages/web/examples/rsxt.rs b/packages/web/examples/rsxt.rs index e5fa19edc..bc6e2276d 100644 --- a/packages/web/examples/rsxt.rs +++ b/packages/web/examples/rsxt.rs @@ -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!" + } } }) }; diff --git a/packages/web/src/lib.rs b/packages/web/src/lib.rs index 060777651..c58d97342 100644 --- a/packages/web/src/lib.rs +++ b/packages/web/src/lib.rs @@ -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