refactor interperting macro into function and don't rely on cx being in scope

This commit is contained in:
Evan Almloff committed 2022-06-04 12:20:56 -05:00
1 parent 0079f7d18b
commit 2bcaa2e43e
5 files changed
+64 -51

No files matched your search

+10 -36
View File
@@ -189,44 +189,18 @@ pub fn rsx(s: TokenStream) -> TokenStream {
use dioxus_rsx_interpreter::captuered_context::CapturedContextBuilder; use dioxus_rsx_interpreter::captuered_context::CapturedContextBuilder;
match CapturedContextBuilder::from_call_body(body) { match CapturedContextBuilder::from_call_body(body) {
Ok(captured) => { Ok(captured) => quote::quote! {
quote::quote! { {
{ LazyNodes::new(|__cx|{
let __line_num = get_line_num(); let captured = #captured;
let __rsx_text_index: RsxContext = cx.consume_context().expect("Hot reload is not avalable on this platform"); let line_num = get_line_num();
// only the insert the rsx text once let text = #rsx_text;
if !__rsx_text_index.read().hm.contains_key(&__line_num){
__rsx_text_index.insert( resolve_scope(line_num, text, captured, __cx)
__line_num.clone(), })
#rsx_text.to_string(),
);
}
LazyNodes::new(move |__cx|{
if let Some(__text) = {
let read = __rsx_text_index.read();
// clone prevents deadlock on nested rsx calls
read.hm.get(&__line_num).cloned()
} {
match interpert_rsx(
__cx,
&__text,
#captured
){
Ok(vnode) => vnode,
Err(err) => {
__rsx_text_index.report_error(err);
__cx.text(format_args!(""))
}
}
}
else {
panic!("rsx: line number {:?} not found in rsx index", __line_num);
}
})
}
} }
.into()
} }
.into(),
Err(err) => err.into_compile_error().into(), Err(err) => err.into_compile_error().into(),
} }
} }
+5 -10
View File
@@ -54,7 +54,7 @@ impl DesktopController {
#[cfg(feature = "hot_reload")] #[cfg(feature = "hot_reload")]
{ {
use dioxus_rsx_interpreter::{ use dioxus_rsx_interpreter::{
error::Error, ErrorHandler, RsxContext, RsxData, SetRsxMessage, error::Error, ErrorHandler, RsxContext, RsxData, SetRsxMessage, RSX_CONTEXT,
}; };
use interprocess::local_socket::{LocalSocketListener, LocalSocketStream}; use interprocess::local_socket::{LocalSocketListener, LocalSocketStream};
use std::io::{BufRead, BufReader, Write}; use std::io::{BufRead, BufReader, Write};
@@ -93,14 +93,9 @@ impl DesktopController {
} }
} }
let context = dom RSX_CONTEXT.set_error_handler(DesktopErrorHandler {
.base_scope() latest_connection: latest_connection_handle,
.provide_root_context(RsxContext::new(RsxData { });
hm: HashMap::new(),
error_handler: Box::new(DesktopErrorHandler {
latest_connection: latest_connection_handle,
}),
}));
std::thread::spawn(move || { std::thread::spawn(move || {
if let Ok(listener) = LocalSocketListener::bind("@dioxus") { if let Ok(listener) = LocalSocketListener::bind("@dioxus") {
@@ -124,7 +119,7 @@ impl DesktopController {
let message: SetRsxMessage = let message: SetRsxMessage =
serde_json::from_str(&buf).unwrap(); serde_json::from_str(&buf).unwrap();
println!("{:?}", message.location); println!("{:?}", message.location);
context.insert(message.location, message.new_text); RSX_CONTEXT.insert(message.location, message.new_text);
} }
Err(err) => { Err(err) => {
if err.kind() != std::io::ErrorKind::WouldBlock { if err.kind() != std::io::ErrorKind::WouldBlock {
+1
View File
@@ -9,6 +9,7 @@ syn = { version = "1.0", features = ["extra-traits"] }
quote = "1.0" quote = "1.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = { vesion = "1.0" } serde_json = { vesion = "1.0" }
lazy_static = "1.4.0"
dioxus-rsx = { path = "../rsx", default-features = false } dioxus-rsx = { path = "../rsx", default-features = false }
dioxus-ssr = { path = "../ssr" } dioxus-ssr = { path = "../ssr" }
+47 -4
View File
@@ -1,6 +1,8 @@
use dioxus_core::{Component, Element, LazyNodes, Scope, VNode}; use captuered_context::CapturedContext;
use dioxus_core::{Component, Element, LazyNodes, NodeFactory, Scope, ScopeState, VNode};
use error::Error; use error::Error;
use interperter::build; use interperter::build;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::panic::Location; use std::panic::Location;
@@ -13,6 +15,12 @@ mod elements;
pub mod error; pub mod error;
mod interperter; mod interperter;
lazy_static! {
/// This a a global store of the current
// Global mutable data is genrally not great, but it allows users to not worry about passing down the text RsxContex every time they switch to hot reloading.
pub static ref RSX_CONTEXT: RsxContext = RsxContext::new(RsxData::default());
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
pub struct CodeLocation { pub struct CodeLocation {
pub file: String, pub file: String,
@@ -20,6 +28,34 @@ pub struct CodeLocation {
pub column: u32, pub column: u32,
} }
pub fn resolve_scope<'a>(
location: CodeLocation,
rsx: &'static str,
captured: CapturedContext<'a>,
factory: NodeFactory<'a>,
) -> VNode<'a> {
let rsx_text_index = &*RSX_CONTEXT;
// only the insert the rsx text once
if !rsx_text_index.read().hm.contains_key(&location) {
rsx_text_index.insert(location.clone(), rsx.to_string());
}
if let Some(text) = {
let read = rsx_text_index.read();
// clone prevents deadlock on nested rsx calls
read.hm.get(&location).cloned()
} {
match interpert_rsx(factory, &text, captured) {
Ok(vnode) => vnode,
Err(err) => {
rsx_text_index.report_error(err);
factory.text(format_args!(""))
}
}
} else {
panic!("rsx: line number {:?} not found in rsx index", location);
}
}
pub fn interpert_rsx<'a, 'b>( pub fn interpert_rsx<'a, 'b>(
factory: dioxus_core::NodeFactory<'a>, factory: dioxus_core::NodeFactory<'a>,
text: &str, text: &str,
@@ -47,9 +83,10 @@ pub struct RsxContext {
data: Arc<RwLock<RsxData>>, data: Arc<RwLock<RsxData>>,
} }
#[derive(Default)]
pub struct RsxData { pub struct RsxData {
pub hm: HashMap<CodeLocation, String>, pub hm: HashMap<CodeLocation, String>,
pub error_handler: Box<dyn ErrorHandler + Send + Sync>, pub error_handler: Option<Box<dyn ErrorHandler>>,
} }
impl std::fmt::Debug for RsxData { impl std::fmt::Debug for RsxData {
@@ -74,11 +111,17 @@ impl RsxContext {
} }
pub fn report_error(&self, error: Error) { pub fn report_error(&self, error: Error) {
self.data.write().unwrap().error_handler.handle_error(error) if let Some(handler) = &self.data.write().unwrap().error_handler {
handler.handle_error(error)
}
}
pub fn set_error_handler(&self, handler: impl ErrorHandler + 'static) {
self.data.write().unwrap().error_handler = Some(Box::new(handler));
} }
} }
pub trait ErrorHandler { pub trait ErrorHandler: Send + Sync {
fn handle_error(&self, err: Error); fn handle_error(&self, err: Error);
} }
+1 -1
View File
@@ -65,6 +65,6 @@ pub mod prelude {
#[cfg(feature = "hot_reload")] #[cfg(feature = "hot_reload")]
pub use dioxus_rsx_interpreter::{ pub use dioxus_rsx_interpreter::{
captuered_context::{CapturedContext, FormattedArg, IfmtArgs}, captuered_context::{CapturedContext, FormattedArg, IfmtArgs},
get_line_num, interpert_rsx, CodeLocation, RsxContext, get_line_num, interpert_rsx, resolve_scope, CodeLocation, RsxContext,
}; };
} }