mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-23 12:43:08 +00:00
refactor interperting macro into function and don't rely on cx being in scope
This commit is contained in:
parent
0079f7d18b
commit
2bcaa2e43e
5 changed files with 64 additions and 51 deletions
|
@ -189,44 +189,18 @@ pub fn rsx(s: TokenStream) -> TokenStream {
|
|||
use dioxus_rsx_interpreter::captuered_context::CapturedContextBuilder;
|
||||
|
||||
match CapturedContextBuilder::from_call_body(body) {
|
||||
Ok(captured) => {
|
||||
quote::quote! {
|
||||
{
|
||||
let __line_num = get_line_num();
|
||||
let __rsx_text_index: RsxContext = cx.consume_context().expect("Hot reload is not avalable on this platform");
|
||||
// only the insert the rsx text once
|
||||
if !__rsx_text_index.read().hm.contains_key(&__line_num){
|
||||
__rsx_text_index.insert(
|
||||
__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);
|
||||
}
|
||||
})
|
||||
}
|
||||
Ok(captured) => quote::quote! {
|
||||
{
|
||||
LazyNodes::new(|__cx|{
|
||||
let captured = #captured;
|
||||
let line_num = get_line_num();
|
||||
let text = #rsx_text;
|
||||
|
||||
resolve_scope(line_num, text, captured, __cx)
|
||||
})
|
||||
}
|
||||
.into()
|
||||
}
|
||||
.into(),
|
||||
Err(err) => err.into_compile_error().into(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ impl DesktopController {
|
|||
#[cfg(feature = "hot_reload")]
|
||||
{
|
||||
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 std::io::{BufRead, BufReader, Write};
|
||||
|
@ -93,14 +93,9 @@ impl DesktopController {
|
|||
}
|
||||
}
|
||||
|
||||
let context = dom
|
||||
.base_scope()
|
||||
.provide_root_context(RsxContext::new(RsxData {
|
||||
hm: HashMap::new(),
|
||||
error_handler: Box::new(DesktopErrorHandler {
|
||||
latest_connection: latest_connection_handle,
|
||||
}),
|
||||
}));
|
||||
RSX_CONTEXT.set_error_handler(DesktopErrorHandler {
|
||||
latest_connection: latest_connection_handle,
|
||||
});
|
||||
|
||||
std::thread::spawn(move || {
|
||||
if let Ok(listener) = LocalSocketListener::bind("@dioxus") {
|
||||
|
@ -124,7 +119,7 @@ impl DesktopController {
|
|||
let message: SetRsxMessage =
|
||||
serde_json::from_str(&buf).unwrap();
|
||||
println!("{:?}", message.location);
|
||||
context.insert(message.location, message.new_text);
|
||||
RSX_CONTEXT.insert(message.location, message.new_text);
|
||||
}
|
||||
Err(err) => {
|
||||
if err.kind() != std::io::ErrorKind::WouldBlock {
|
||||
|
|
|
@ -9,6 +9,7 @@ syn = { version = "1.0", features = ["extra-traits"] }
|
|||
quote = "1.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = { vesion = "1.0" }
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
dioxus-rsx = { path = "../rsx", default-features = false }
|
||||
dioxus-ssr = { path = "../ssr" }
|
||||
|
|
|
@ -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 interperter::build;
|
||||
use lazy_static::lazy_static;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::panic::Location;
|
||||
|
@ -13,6 +15,12 @@ mod elements;
|
|||
pub mod error;
|
||||
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)]
|
||||
pub struct CodeLocation {
|
||||
pub file: String,
|
||||
|
@ -20,6 +28,34 @@ pub struct CodeLocation {
|
|||
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>(
|
||||
factory: dioxus_core::NodeFactory<'a>,
|
||||
text: &str,
|
||||
|
@ -47,9 +83,10 @@ pub struct RsxContext {
|
|||
data: Arc<RwLock<RsxData>>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RsxData {
|
||||
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 {
|
||||
|
@ -74,11 +111,17 @@ impl RsxContext {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,6 @@ pub mod prelude {
|
|||
#[cfg(feature = "hot_reload")]
|
||||
pub use dioxus_rsx_interpreter::{
|
||||
captuered_context::{CapturedContext, FormattedArg, IfmtArgs},
|
||||
get_line_num, interpert_rsx, CodeLocation, RsxContext,
|
||||
get_line_num, interpert_rsx, resolve_scope, CodeLocation, RsxContext,
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue