From 2eec2bc6734b345d8efc9a589bda777a68a2cd85 Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Mon, 5 Feb 2024 21:51:49 +0800 Subject: [PATCH 01/43] add rustfmt support --- packages/cli/src/cli/autoformat.rs | 50 ++++++++++++++++++++++++++++-- packages/cli/src/error.rs | 3 ++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index 87d780524..d2e894d82 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -10,6 +10,10 @@ use super::*; /// Format some rsx #[derive(Clone, Debug, Parser)] pub struct Autoformat { + /// Run rustfmt before the dioxus formatter` + #[clap(long)] + pub rustfmt: bool, + /// Run in 'check' mode. Exits with 0 if input is formatted correctly. Exits /// with 1 and prints a diff if formatting is required. #[clap(short, long)] @@ -36,6 +40,7 @@ impl Autoformat { raw, file, split_line_attributes, + rustfmt, .. } = self; @@ -60,14 +65,47 @@ impl Autoformat { // Format single file if let Some(file) = file { - refactor_file(file, split_line_attributes)?; + refactor_file(file, split_line_attributes, rustfmt)?; } Ok(()) } } -fn refactor_file(file: String, split_line_attributes: bool) -> Result<(), Error> { +/// Call rustfmt to format code, i32 as exitcode +fn rustfmt(input: String) -> Result { + use std::thread; + + let mut child = Command::new("rustfmt") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .map_err(|e| Error::IO(e))?; + + let mut stdin = child.stdin.take().unwrap(); + let pass_in = input.to_string(); + let handle = thread::spawn(move || -> Result<()> { + stdin + .write_all(pass_in.as_bytes()) + .map_err(|e| Error::IO(e))?; + Ok(()) + }); + handle.join().unwrap()?; + + let output = child.wait_with_output().map_err(|e| Error::IO(e))?; + + if let Some(exit_code) = output.status.code() { + if exit_code != 0 { + return Err(Error::ExitCodeNotZero(exit_code)); + } + } + + let output = String::from_utf8(output.stdout).map_err(|e| Error::Other(e.into()))?; + + Ok(output) +} + +fn refactor_file(file: String, split_line_attributes: bool, do_rustfmt: bool) -> Result<(), Error> { let indent = indentation_for(".", split_line_attributes)?; let file_content = if file == "-" { let mut contents = String::new(); @@ -76,10 +114,15 @@ fn refactor_file(file: String, split_line_attributes: bool) -> Result<(), Error> } else { fs::read_to_string(&file) }; - let Ok(s) = file_content else { + let Ok(mut s) = file_content else { eprintln!("failed to open file: {}", file_content.unwrap_err()); exit(1); }; + + if do_rustfmt { + s = rustfmt(s)?; + } + let edits = dioxus_autofmt::fmt_file(&s, indent); let out = dioxus_autofmt::apply_formats(&s, edits); @@ -280,6 +323,7 @@ async fn test_auto_fmt() { .to_string(); let fmt = Autoformat { + rustfmt: false, check: false, raw: Some(test_rsx), file: None, diff --git a/packages/cli/src/error.rs b/packages/cli/src/error.rs index 35eea7eab..98c7fc36b 100644 --- a/packages/cli/src/error.rs +++ b/packages/cli/src/error.rs @@ -46,6 +46,9 @@ pub enum Error { #[error(transparent)] Other(#[from] anyhow::Error), + + #[error("Child process exited with {0}")] + ExitCodeNotZero(i32), } impl From<&str> for Error { From f40e2f3cef474d5581d7ec560d20069da79e6376 Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Tue, 6 Feb 2024 20:53:28 +0800 Subject: [PATCH 02/43] replace gitignore with ignore --- Cargo.lock | 12 +-- Cargo.toml | 31 ++++--- packages/autofmt/src/lib.rs | 7 ++ packages/cli/Cargo.toml | 5 +- packages/cli/src/cli/autoformat.rs | 129 ++++++++++++----------------- 5 files changed, 78 insertions(+), 106 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 965954c12..2fa0eaccd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2501,11 +2501,11 @@ dependencies = [ "flate2", "fs_extra", "futures-util", - "gitignore", "headers 0.3.9", "html_parser", "hyper 0.14.28", "hyper-rustls 0.23.2", + "ignore", "indicatif", "interprocess-docfix", "lazy_static", @@ -2514,6 +2514,7 @@ dependencies = [ "mlua", "notify", "open", + "rayon", "reqwest", "rsx-rosetta", "serde", @@ -4119,15 +4120,6 @@ dependencies = [ "url", ] -[[package]] -name = "gitignore" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d051488d9a601181a9b90c9ad8ae7e8251d642ddd2463008f2f5019d255bd89" -dependencies = [ - "glob", -] - [[package]] name = "gix-actor" version = "0.28.1" diff --git a/Cargo.toml b/Cargo.toml index a3de51715..31862400d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,23 +58,23 @@ version = "0.4.3" [workspace.dependencies] dioxus = { path = "packages/dioxus", version = "0.4.0" } dioxus-core = { path = "packages/core", version = "0.4.2" } -dioxus-core-macro = { path = "packages/core-macro", version = "0.4.0" } -dioxus-router = { path = "packages/router", version = "0.4.1" } +dioxus-core-macro = { path = "packages/core-macro", version = "0.4.0" } +dioxus-router = { path = "packages/router", version = "0.4.1" } dioxus-router-macro = { path = "packages/router-macro", version = "0.4.1" } -dioxus-html = { path = "packages/html", default-features = false, version = "0.4.0" } -dioxus-html-internal-macro = { path = "packages/html-internal-macro", version = "0.4.0" } +dioxus-html = { path = "packages/html", default-features = false, version = "0.4.0" } +dioxus-html-internal-macro = { path = "packages/html-internal-macro", version = "0.4.0" } dioxus-hooks = { path = "packages/hooks", version = "0.4.0" } -dioxus-web = { path = "packages/web", version = "0.4.0" } -dioxus-ssr = { path = "packages/ssr", version = "0.4.0" } -dioxus-desktop = { path = "packages/desktop", version = "0.4.0" } -dioxus-mobile = { path = "packages/mobile", version = "0.4.0" } +dioxus-web = { path = "packages/web", version = "0.4.0" } +dioxus-ssr = { path = "packages/ssr", version = "0.4.0" } +dioxus-desktop = { path = "packages/desktop", version = "0.4.0" } +dioxus-mobile = { path = "packages/mobile", version = "0.4.0" } dioxus-interpreter-js = { path = "packages/interpreter", version = "0.4.0" } -fermi = { path = "packages/fermi", version = "0.4.0" } -dioxus-liveview = { path = "packages/liveview", version = "0.4.0" } -dioxus-autofmt = { path = "packages/autofmt", version = "0.4.0" } -dioxus-check = { path = "packages/check", version = "0.4.0" } -dioxus-rsx = { path = "packages/rsx", version = "0.4.0" } -dioxus-tui = { path = "packages/dioxus-tui", version = "0.4.0" } +fermi = { path = "packages/fermi", version = "0.4.0" } +dioxus-liveview = { path = "packages/liveview", version = "0.4.0" } +dioxus-autofmt = { path = "packages/autofmt", version = "0.4.0" } +dioxus-check = { path = "packages/check", version = "0.4.0" } +dioxus-rsx = { path = "packages/rsx", version = "0.4.0" } +dioxus-tui = { path = "packages/dioxus-tui", version = "0.4.0" } plasmo = { path = "packages/rink", version = "0.4.0" } dioxus-native-core = { path = "packages/native-core", version = "0.4.0" } dioxus-native-core-macro = { path = "packages/native-core-macro", version = "0.4.0" } @@ -83,7 +83,7 @@ dioxus-signals = { path = "packages/signals" } dioxus-cli-config = { path = "packages/cli-config", version = "0.4.1" } generational-box = { path = "packages/generational-box", version = "0.4.3" } dioxus-hot-reload = { path = "packages/hot-reload", version = "0.4.0" } -dioxus-fullstack = { path = "packages/fullstack", version = "0.4.1" } +dioxus-fullstack = { path = "packages/fullstack", version = "0.4.1" } dioxus_server_macro = { path = "packages/server-macro", version = "0.4.1" } tracing = "0.1.37" tracing-futures = "0.2.5" @@ -144,4 +144,3 @@ thiserror = { workspace = true } manganis = { workspace = true } tracing-subscriber = "0.3.17" http-range = "0.1.5" - diff --git a/packages/autofmt/src/lib.rs b/packages/autofmt/src/lib.rs index e40b873d6..953f052b0 100644 --- a/packages/autofmt/src/lib.rs +++ b/packages/autofmt/src/lib.rs @@ -240,3 +240,10 @@ pub(crate) fn write_ifmt(input: &IfmtInput, writable: &mut impl Write) -> std::f let display = DisplayIfmt(input); write!(writable, "{}", display) } + +/// Call rustfmt to format code, i32 as exitcode +pub fn rustfmt(input: &str) -> Option { + let syntax_tree = syn::parse_file(input).ok()?; + let output = prettyplease::unparse(&syntax_tree); + Some(output) +} diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index 0be33e9ae..dc53b7442 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -26,7 +26,7 @@ fs_extra = "1.2.0" cargo_toml = "0.18.0" futures-util.workspace = true notify = { version = "5.0.0-pre.16", features = ["serde"] } -html_parser = { workspace = true } +html_parser = { workspace = true } cargo_metadata = "0.18.1" tokio = { version = "1.16.1", features = ["fs", "sync", "rt", "macros"] } atty = "0.2.14" @@ -36,6 +36,7 @@ hyper = "0.14.17" hyper-rustls = "0.23.2" indicatif = "0.17.5" subprocess = "0.2.9" +rayon = "1.8.0" axum = { version = "0.5.1", features = ["ws", "headers"] } axum-server = { version = "0.5.1", features = ["tls-rustls"] } @@ -84,7 +85,7 @@ dioxus-html = { workspace = true, features = ["hot-reload-context"] } dioxus-core = { workspace = true, features = ["serialize"] } dioxus-hot-reload = { workspace = true } interprocess-docfix = { version = "1.2.2" } -gitignore = "1.0.8" +ignore = "0.4.22" [features] default = [] diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index d2e894d82..01612a109 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -1,6 +1,6 @@ use dioxus_autofmt::{IndentOptions, IndentType}; -use futures_util::{stream::FuturesUnordered, StreamExt}; -use std::{fs, path::Path, process::exit}; +use rayon::prelude::*; +use std::{fs, io, path::Path, process::exit}; use super::*; @@ -40,13 +40,14 @@ impl Autoformat { raw, file, split_line_attributes, - rustfmt, + rustfmt: do_rustfmt, .. } = self; // Default to formatting the project if raw.is_none() && file.is_none() { - if let Err(e) = autoformat_project(check, split_line_attributes).await { + println!("format project !"); + if let Err(e) = autoformat_project(check, split_line_attributes, do_rustfmt).await { eprintln!("error formatting project: {}", e); exit(1); } @@ -65,46 +66,13 @@ impl Autoformat { // Format single file if let Some(file) = file { - refactor_file(file, split_line_attributes, rustfmt)?; + refactor_file(file, split_line_attributes, do_rustfmt)?; } Ok(()) } } -/// Call rustfmt to format code, i32 as exitcode -fn rustfmt(input: String) -> Result { - use std::thread; - - let mut child = Command::new("rustfmt") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .map_err(|e| Error::IO(e))?; - - let mut stdin = child.stdin.take().unwrap(); - let pass_in = input.to_string(); - let handle = thread::spawn(move || -> Result<()> { - stdin - .write_all(pass_in.as_bytes()) - .map_err(|e| Error::IO(e))?; - Ok(()) - }); - handle.join().unwrap()?; - - let output = child.wait_with_output().map_err(|e| Error::IO(e))?; - - if let Some(exit_code) = output.status.code() { - if exit_code != 0 { - return Err(Error::ExitCodeNotZero(exit_code)); - } - } - - let output = String::from_utf8(output.stdout).map_err(|e| Error::Other(e.into()))?; - - Ok(output) -} - fn refactor_file(file: String, split_line_attributes: bool, do_rustfmt: bool) -> Result<(), Error> { let indent = indentation_for(".", split_line_attributes)?; let file_content = if file == "-" { @@ -120,7 +88,7 @@ fn refactor_file(file: String, split_line_attributes: bool, do_rustfmt: bool) -> }; if do_rustfmt { - s = rustfmt(s)?; + s = dioxus_autofmt::rustfmt(&s).ok_or_else(|| Error::ParseError("Syntax Error".into()))?; } let edits = dioxus_autofmt::fmt_file(&s, indent); @@ -137,25 +105,21 @@ fn refactor_file(file: String, split_line_attributes: bool, do_rustfmt: bool) -> Ok(()) } -fn get_project_files(config: &CrateConfig) -> Vec { - let mut files = vec![]; - - let gitignore_path = config.crate_dir.join(".gitignore"); - if gitignore_path.is_file() { - let gitigno = gitignore::File::new(gitignore_path.as_path()).unwrap(); - if let Ok(git_files) = gitigno.included_files() { - let git_files = git_files - .into_iter() - .filter(|f| f.ends_with(".rs") && !is_target_dir(f)); - files.extend(git_files) - }; - } else { - collect_rs_files(&config.crate_dir, &mut files); +use std::ffi::OsStr; +fn get_project_files() -> Vec { + let mut files = Vec::new(); + for result in ignore::Walk::new("./") { + let path = result.unwrap().into_path(); + if let Some(ext) = path.extension() { + if ext == OsStr::new("rs") { + files.push(path); + } + } } - files } +#[allow(dead_code)] fn is_target_dir(file: &Path) -> bool { let stripped = if let Ok(cwd) = std::env::current_dir() { file.strip_prefix(cwd).unwrap_or(file) @@ -169,18 +133,30 @@ fn is_target_dir(file: &Path) -> bool { } } -async fn format_file( - path: impl AsRef, - indent: IndentOptions, -) -> Result { - let contents = tokio::fs::read_to_string(&path).await?; +fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) -> Result { + let mut contents = fs::read_to_string(&path)?; + let mut if_write = false; + if do_rustfmt { + let formatted = dioxus_autofmt::rustfmt(&contents) + .ok_or_else(|| Error::ParseError("Syntax Error".into()))?; + if contents != formatted { + if_write = true; + contents = formatted; + } + } + + println!("at {} : {:#?}", path.as_ref().display(), &contents); let edits = dioxus_autofmt::fmt_file(&contents, indent); let len = edits.len(); if !edits.is_empty() { + if_write = true; + } + + if if_write { let out = dioxus_autofmt::apply_formats(&contents, edits); - tokio::fs::write(path, out).await?; + fs::write(path, out)?; } Ok(len) @@ -190,11 +166,15 @@ async fn format_file( /// /// Runs using Tokio for multithreading, so it should be really really fast /// -/// Doesn't do mod-descending, so it will still try to format unreachable files. TODO. -async fn autoformat_project(check: bool, split_line_attributes: bool) -> Result<()> { - let crate_config = dioxus_cli_config::CrateConfig::new(None)?; +/// Doesnhttps://www.rustwiki.org.cn/zh-CN/std/'t do mod-descending, so it will still try to format unreachable files. TODO. +async fn autoformat_project( + check: bool, + split_line_attributes: bool, + do_rustfmt: bool, +) -> Result<()> { + let files_to_format = get_project_files(); - let files_to_format = get_project_files(&crate_config); + dbg!(&files_to_format); if files_to_format.is_empty() { return Ok(()); @@ -203,26 +183,18 @@ async fn autoformat_project(check: bool, split_line_attributes: bool) -> Result< let indent = indentation_for(&files_to_format[0], split_line_attributes)?; let counts = files_to_format - .into_iter() - .map(|path| async { - let path_clone = path.clone(); - let res = tokio::spawn(format_file(path, indent.clone())).await; - + .into_par_iter() + .map(|path| { + let res = format_file(&path, indent.clone(), do_rustfmt); match res { + Ok(cnt) => Some(cnt), Err(err) => { - eprintln!("error formatting file: {}\n{err}", path_clone.display()); + eprintln!("error formatting file : {}\n{:#?}", path.display(), err); None } - Ok(Err(err)) => { - eprintln!("error formatting file: {}\n{err}", path_clone.display()); - None - } - Ok(Ok(res)) => Some(res), } }) - .collect::>() - .collect::>() - .await; + .collect::>(); let files_formatted: usize = counts.into_iter().flatten().sum(); @@ -281,6 +253,7 @@ fn indentation_for( )) } +#[allow(dead_code)] fn collect_rs_files(folder: &impl AsRef, files: &mut Vec) { if is_target_dir(folder.as_ref()) { return; From 192fa3471b2b7ceecd16ec4cdca0abeadb1bd182 Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Tue, 6 Feb 2024 20:56:12 +0800 Subject: [PATCH 03/43] clippy fix --- packages/cli/src/cli/autoformat.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index 01612a109..bcf9b266f 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -1,6 +1,6 @@ use dioxus_autofmt::{IndentOptions, IndentType}; use rayon::prelude::*; -use std::{fs, io, path::Path, process::exit}; +use std::{fs, path::Path, process::exit}; use super::*; From d170304a596198999c0617a94103a17381f903cd Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Tue, 6 Feb 2024 21:01:33 +0800 Subject: [PATCH 04/43] remove dead code --- packages/cli/src/cli/autoformat.rs | 43 +----------------------------- 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index bcf9b266f..b1ec83a66 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -1,6 +1,6 @@ use dioxus_autofmt::{IndentOptions, IndentType}; use rayon::prelude::*; -use std::{fs, path::Path, process::exit}; +use std::{fs, io, path::Path, process::exit}; use super::*; @@ -119,20 +119,6 @@ fn get_project_files() -> Vec { files } -#[allow(dead_code)] -fn is_target_dir(file: &Path) -> bool { - let stripped = if let Ok(cwd) = std::env::current_dir() { - file.strip_prefix(cwd).unwrap_or(file) - } else { - file - }; - if let Some(first) = stripped.components().next() { - first.as_os_str() == "target" - } else { - false - } -} - fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) -> Result { let mut contents = fs::read_to_string(&path)?; let mut if_write = false; @@ -174,8 +160,6 @@ async fn autoformat_project( ) -> Result<()> { let files_to_format = get_project_files(); - dbg!(&files_to_format); - if files_to_format.is_empty() { return Ok(()); } @@ -253,31 +237,6 @@ fn indentation_for( )) } -#[allow(dead_code)] -fn collect_rs_files(folder: &impl AsRef, files: &mut Vec) { - if is_target_dir(folder.as_ref()) { - return; - } - let Ok(folder) = folder.as_ref().read_dir() else { - return; - }; - // load the gitignore - for entry in folder { - let Ok(entry) = entry else { - continue; - }; - let path = entry.path(); - if path.is_dir() { - collect_rs_files(&path, files); - } - if let Some(ext) = path.extension() { - if ext == "rs" && !is_target_dir(&path) { - files.push(path); - } - } - } -} - #[tokio::test] async fn test_auto_fmt() { let test_rsx = r#" From 71125c22e0fe767a5e0c8e211b50d649fb380058 Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Tue, 6 Feb 2024 21:03:04 +0800 Subject: [PATCH 05/43] remove unused import --- packages/cli/src/cli/autoformat.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index b1ec83a66..b2e41a6c3 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -1,6 +1,6 @@ use dioxus_autofmt::{IndentOptions, IndentType}; use rayon::prelude::*; -use std::{fs, io, path::Path, process::exit}; +use std::{fs, path::Path, process::exit}; use super::*; From 82fc7acaa5c2712e5b0b0ca7fa2d1593926b1202 Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Tue, 6 Feb 2024 21:04:37 +0800 Subject: [PATCH 06/43] remove debug print --- packages/cli/src/cli/autoformat.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index b2e41a6c3..d487afe1e 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -46,7 +46,6 @@ impl Autoformat { // Default to formatting the project if raw.is_none() && file.is_none() { - println!("format project !"); if let Err(e) = autoformat_project(check, split_line_attributes, do_rustfmt).await { eprintln!("error formatting project: {}", e); exit(1); @@ -131,8 +130,6 @@ fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) } } - println!("at {} : {:#?}", path.as_ref().display(), &contents); - let edits = dioxus_autofmt::fmt_file(&contents, indent); let len = edits.len(); From c89a4b37dc7c1423ef698b25560d081018cb31f0 Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Wed, 7 Feb 2024 22:35:55 +0800 Subject: [PATCH 07/43] remove the link in comment and unused error variant --- packages/cli/src/cli/autoformat.rs | 4 ++-- packages/cli/src/error.rs | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index d487afe1e..83fbdc1b8 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -147,9 +147,9 @@ fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) /// Read every .rs file accessible when considering the .gitignore and try to format it /// -/// Runs using Tokio for multithreading, so it should be really really fast +/// Runs using rayon for multithreading, so it should be really really fast /// -/// Doesnhttps://www.rustwiki.org.cn/zh-CN/std/'t do mod-descending, so it will still try to format unreachable files. TODO. +/// Doesn't do mod-descending, so it will still try to format unreachable files. TODO. async fn autoformat_project( check: bool, split_line_attributes: bool, diff --git a/packages/cli/src/error.rs b/packages/cli/src/error.rs index 98c7fc36b..35eea7eab 100644 --- a/packages/cli/src/error.rs +++ b/packages/cli/src/error.rs @@ -46,9 +46,6 @@ pub enum Error { #[error(transparent)] Other(#[from] anyhow::Error), - - #[error("Child process exited with {0}")] - ExitCodeNotZero(i32), } impl From<&str> for Error { From 1af8f56e89113802c209158dc46b6ec34b6386e0 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Wed, 7 Feb 2024 08:53:21 -0600 Subject: [PATCH 08/43] make target an associated type --- packages/generational-box/src/lib.rs | 11 +- packages/generational-box/src/sync.rs | 2 +- packages/generational-box/src/unsync.rs | 2 +- packages/signals/src/copy_value.rs | 16 ++- packages/signals/src/global/memo.rs | 10 +- packages/signals/src/global/signal.rs | 25 ++-- packages/signals/src/map.rs | 153 +++++++++++------------ packages/signals/src/read.rs | 47 ++++--- packages/signals/src/read_only_signal.rs | 10 +- packages/signals/src/signal.rs | 23 ++-- packages/signals/src/write.rs | 47 ++++--- 11 files changed, 194 insertions(+), 152 deletions(-) diff --git a/packages/generational-box/src/lib.rs b/packages/generational-box/src/lib.rs index 052f95a37..341ef89bf 100644 --- a/packages/generational-box/src/lib.rs +++ b/packages/generational-box/src/lib.rs @@ -228,9 +228,9 @@ pub trait Storage: AnyStorage + 'static { /// A trait for any storage backing type. pub trait AnyStorage: Default { /// The reference this storage type returns. - type Ref: Deref; + type Ref: Deref + 'static; /// The mutable reference this storage type returns. - type Mut: DerefMut; + type Mut: DerefMut + 'static; /// Try to map the mutable ref. fn try_map_mut( @@ -247,13 +247,16 @@ pub trait AnyStorage: Default { } /// Try to map the ref. - fn try_map( + fn try_map( ref_: Self::Ref, f: impl FnOnce(&T) -> Option<&U>, ) -> Option>; /// Map the ref. - fn map(ref_: Self::Ref, f: impl FnOnce(&T) -> &U) -> Self::Ref { + fn map( + ref_: Self::Ref, + f: impl FnOnce(&T) -> &U, + ) -> Self::Ref { Self::try_map(ref_, |v| Some(f(v))).unwrap() } diff --git a/packages/generational-box/src/sync.rs b/packages/generational-box/src/sync.rs index 5241fb22e..1edd9a12e 100644 --- a/packages/generational-box/src/sync.rs +++ b/packages/generational-box/src/sync.rs @@ -23,7 +23,7 @@ impl AnyStorage for SyncStorage { type Ref = GenerationalRef>; type Mut = GenerationalRefMut>; - fn try_map( + fn try_map( ref_: Self::Ref, f: impl FnOnce(&I) -> Option<&U>, ) -> Option> { diff --git a/packages/generational-box/src/unsync.rs b/packages/generational-box/src/unsync.rs index e1f5f9df9..da08cf4c4 100644 --- a/packages/generational-box/src/unsync.rs +++ b/packages/generational-box/src/unsync.rs @@ -92,7 +92,7 @@ impl AnyStorage for UnsyncStorage { type Ref = GenerationalRef>; type Mut = GenerationalRefMut>; - fn try_map( + fn try_map( _self: Self::Ref, f: impl FnOnce(&I) -> Option<&U>, ) -> Option> { diff --git a/packages/signals/src/copy_value.rs b/packages/signals/src/copy_value.rs index 142e6d800..bf52d090c 100644 --- a/packages/signals/src/copy_value.rs +++ b/packages/signals/src/copy_value.rs @@ -204,14 +204,18 @@ impl> CopyValue { } } -impl> Readable for CopyValue { +impl> Readable for CopyValue { + type Target = T; type Ref = S::Ref; - fn map_ref &U>(ref_: Self::Ref, f: F) -> Self::Ref { + fn map_ref &U>( + ref_: Self::Ref, + f: F, + ) -> Self::Ref { S::map(ref_, f) } - fn try_map_ref Option<&U>>( + fn try_map_ref Option<&U>>( ref_: Self::Ref, f: F, ) -> Option> { @@ -227,17 +231,17 @@ impl> Readable for CopyValue { } } -impl> Writable for CopyValue { +impl> Writable for CopyValue { type Mut = S::Mut; - fn map_mut &mut U>( + fn map_mut &mut U>( mut_: Self::Mut, f: F, ) -> Self::Mut { S::map_mut(mut_, f) } - fn try_map_mut Option<&mut U>>( + fn try_map_mut Option<&mut U>>( mut_: Self::Mut, f: F, ) -> Option> { diff --git a/packages/signals/src/global/memo.rs b/packages/signals/src/global/memo.rs index d48d4ffa5..6ab7c3738 100644 --- a/packages/signals/src/global/memo.rs +++ b/packages/signals/src/global/memo.rs @@ -51,14 +51,18 @@ impl GlobalMemo { } } -impl Readable for GlobalMemo { +impl Readable for GlobalMemo { + type Target = T; type Ref = generational_box::GenerationalRef>; - fn map_ref &U>(ref_: Self::Ref, f: F) -> Self::Ref { + fn map_ref &U>( + ref_: Self::Ref, + f: F, + ) -> Self::Ref { ::map(ref_, f) } - fn try_map_ref Option<&U>>( + fn try_map_ref Option<&U>>( ref_: Self::Ref, f: F, ) -> Option> { diff --git a/packages/signals/src/global/signal.rs b/packages/signals/src/global/signal.rs index 96db09cca..99ef1d5e6 100644 --- a/packages/signals/src/global/signal.rs +++ b/packages/signals/src/global/signal.rs @@ -65,7 +65,8 @@ impl GlobalSignal { &self, f: impl Fn(&T) -> &O + 'static, ) -> MappedSignal>> { - MappedSignal::new(self.signal(), f) + // MappedSignal::new(self.signal(), f) + todo!() } /// Get the generational id of the signal. @@ -74,14 +75,18 @@ impl GlobalSignal { } } -impl Readable for GlobalSignal { +impl Readable for GlobalSignal { + type Target = T; type Ref = generational_box::GenerationalRef>; - fn map_ref &U>(ref_: Self::Ref, f: F) -> Self::Ref { + fn map_ref &U>( + ref_: Self::Ref, + f: F, + ) -> Self::Ref { ::map(ref_, f) } - fn try_map_ref Option<&U>>( + fn try_map_ref Option<&U>>( ref_: Self::Ref, f: F, ) -> Option> { @@ -99,17 +104,21 @@ impl Readable for GlobalSignal { } } -impl Writable for GlobalSignal { +impl Writable for GlobalSignal { type Mut = Write; - fn map_mut &mut U>( + fn map_mut &mut U>( ref_: Self::Mut, f: F, ) -> Self::Mut { Write::map(ref_, f) } - fn try_map_mut Option<&mut U>>( + fn try_map_mut< + I: ?Sized + 'static, + U: ?Sized + 'static, + F: FnOnce(&mut I) -> Option<&mut U>, + >( ref_: Self::Mut, f: F, ) -> Option> { @@ -151,7 +160,7 @@ impl Deref for GlobalSignal { // Then move that value into the closure. We assume that the closure now has a in memory layout of Self. let uninit_closure = move || { - as Readable>::read(unsafe { &*uninit_callable.as_ptr() }).clone() + as Readable>::read(unsafe { &*uninit_callable.as_ptr() }).clone() }; // Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure. diff --git a/packages/signals/src/map.rs b/packages/signals/src/map.rs index 640ca9604..b23d82ef8 100644 --- a/packages/signals/src/map.rs +++ b/packages/signals/src/map.rs @@ -3,112 +3,105 @@ use crate::CopyValue; use crate::Signal; use crate::SignalData; use dioxus_core::ScopeId; +use generational_box::AnyStorage; use generational_box::Storage; +use generational_box::UnsyncStorage; use std::fmt::Debug; use std::fmt::Display; /// A read only signal that has been mapped to a new type. -pub struct MappedSignal { - origin_scope: ScopeId, - mapping: CopyValue U>>, +pub struct MappedSignal { + mapping: CopyValue S::Ref>>, } impl MappedSignal<()> { /// Create a new mapped signal. - pub fn new( - signal: Signal, - mapping: impl Fn(&T) -> &U + 'static, - ) -> MappedSignal> + pub fn new(readable: R, mapping: impl Fn(&T) -> &U + 'static) -> MappedSignal where S: Storage>, U: ?Sized, { - MappedSignal { - origin_scope: signal.origin_scope(), - mapping: CopyValue::new(Box::new(move || S::map(signal.read(), &mapping))), - } + todo!() + // MappedSignal { + // mapping: CopyValue::new(Box::new(move || S::map(signal.read(), &mapping))), + // } } } -impl MappedSignal { - /// Get the scope that the signal was created in. - pub fn origin_scope(&self) -> ScopeId { - self.origin_scope - } +// impl MappedSignal { +// /// Get the current value of the signal. This will subscribe the current scope to the signal. +// pub fn read(&self) -> U { +// (self.mapping.read())() +// } - /// Get the current value of the signal. This will subscribe the current scope to the signal. - pub fn read(&self) -> U { - (self.mapping.read())() - } +// /// Run a closure with a reference to the signal's value. +// pub fn with(&self, f: impl FnOnce(U) -> O) -> O { +// f(self.read()) +// } +// } - /// Run a closure with a reference to the signal's value. - pub fn with(&self, f: impl FnOnce(U) -> O) -> O { - f(self.read()) - } -} +// impl MappedSignal { +// /// Get the current value of the signal. This will subscribe the current scope to the signal. +// pub fn value(&self) -> U { +// self.read().clone() +// } +// } -impl MappedSignal { - /// Get the current value of the signal. This will subscribe the current scope to the signal. - pub fn value(&self) -> U { - self.read().clone() - } -} +// impl PartialEq for MappedSignal { +// fn eq(&self, other: &Self) -> bool { +// self.mapping == other.mapping +// } +// } -impl PartialEq for MappedSignal { - fn eq(&self, other: &Self) -> bool { - self.mapping == other.mapping - } -} +// impl std::clone::Clone for MappedSignal { +// fn clone(&self) -> Self { +// *self +// } +// } -impl std::clone::Clone for MappedSignal { - fn clone(&self) -> Self { - *self - } -} +// impl Copy for MappedSignal {} -impl Copy for MappedSignal {} +// impl Display for MappedSignal { +// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +// self.with(|v| Display::fmt(&v, f)) +// } +// } -impl Display for MappedSignal { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.with(|v| Display::fmt(&v, f)) - } -} +// impl Debug for MappedSignal { +// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +// self.with(|v| Debug::fmt(&v, f)) +// } +// } -impl Debug for MappedSignal { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.with(|v| Debug::fmt(&v, f)) - } -} +// impl std::ops::Deref for MappedSignal { +// type Target = dyn Fn() -> T; -impl std::ops::Deref for MappedSignal { - type Target = dyn Fn() -> T; +// fn deref(&self) -> &Self::Target { +// // https://github.com/dtolnay/case-studies/tree/master/callable-types - fn deref(&self) -> &Self::Target { - // https://github.com/dtolnay/case-studies/tree/master/callable-types +// // First we create a closure that captures something with the Same in memory layout as Self (MaybeUninit). +// let uninit_callable = std::mem::MaybeUninit::::uninit(); +// // Then move that value into the closure. We assume that the closure now has a in memory layout of Self. +// let uninit_closure = move || Self::read(unsafe { &*uninit_callable.as_ptr() }); - // First we create a closure that captures something with the Same in memory layout as Self (MaybeUninit). - let uninit_callable = std::mem::MaybeUninit::::uninit(); - // Then move that value into the closure. We assume that the closure now has a in memory layout of Self. - let uninit_closure = move || Self::read(unsafe { &*uninit_callable.as_ptr() }); +// // Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure. +// let size_of_closure = std::mem::size_of_val(&uninit_closure); +// assert_eq!(size_of_closure, std::mem::size_of::()); - // Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure. - let size_of_closure = std::mem::size_of_val(&uninit_closure); - assert_eq!(size_of_closure, std::mem::size_of::()); +// // Then cast the lifetime of the closure to the lifetime of &self. +// fn cast_lifetime<'a, T>(_a: &T, b: &'a T) -> &'a T { +// b +// } +// let reference_to_closure = cast_lifetime( +// { +// // The real closure that we will never use. +// &uninit_closure +// }, +// // We transmute self into a reference to the closure. This is safe because we know that the closure has the same memory layout as Self so &Closure == &Self. +// unsafe { std::mem::transmute(self) }, +// ); - // Then cast the lifetime of the closure to the lifetime of &self. - fn cast_lifetime<'a, T>(_a: &T, b: &'a T) -> &'a T { - b - } - let reference_to_closure = cast_lifetime( - { - // The real closure that we will never use. - &uninit_closure - }, - // We transmute self into a reference to the closure. This is safe because we know that the closure has the same memory layout as Self so &Closure == &Self. - unsafe { std::mem::transmute(self) }, - ); - - // Cast the closure to a trait object. - reference_to_closure as &Self::Target - } -} +// // Cast the closure to a trait object. +// reference_to_closure as &Self::Target +// } +// } diff --git a/packages/signals/src/read.rs b/packages/signals/src/read.rs index 14bf14580..c54095769 100644 --- a/packages/signals/src/read.rs +++ b/packages/signals/src/read.rs @@ -1,66 +1,73 @@ -use std::{mem::MaybeUninit, ops::Deref}; +use std::{ + mem::MaybeUninit, + ops::{Deref, Index}, +}; /// A trait for states that can be read from like [`crate::Signal`], [`crate::GlobalSignal`], or [`crate::ReadOnlySignal`]. You may choose to accept this trait as a parameter instead of the concrete type to allow for more flexibility in your API. For example, instead of creating two functions, one that accepts a [`crate::Signal`] and one that accepts a [`crate::GlobalSignal`], you can create one function that accepts a [`Readable`] type. -pub trait Readable { +pub trait Readable { + /// The target type of the reference. + type Target: ?Sized + 'static; + /// The type of the reference. type Ref: Deref; /// Map the reference to a new type. - fn map_ref &U>(ref_: Self::Ref, f: F) -> Self::Ref; + fn map_ref &U>(ref_: Self::Ref, f: F) + -> Self::Ref; /// Try to map the reference to a new type. - fn try_map_ref Option<&U>>( + fn try_map_ref Option<&U>>( ref_: Self::Ref, f: F, ) -> Option>; /// Try to get the current value of the state. If this is a signal, this will subscribe the current scope to the signal. If the value has been dropped, this will panic. - fn try_read(&self) -> Result, generational_box::BorrowError>; + fn try_read(&self) -> Result, generational_box::BorrowError>; /// Get the current value of the state. If this is a signal, this will subscribe the current scope to the signal. If the value has been dropped, this will panic. #[track_caller] - fn read(&self) -> Self::Ref { + fn read(&self) -> Self::Ref { self.try_read().unwrap() } /// Get the current value of the state without subscribing to updates. If the value has been dropped, this will panic. - fn peek(&self) -> Self::Ref; + fn peek(&self) -> Self::Ref; /// Clone the inner value and return it. If the value has been dropped, this will panic. #[track_caller] - fn cloned(&self) -> T + fn cloned(&self) -> Self::Target where - T: Clone, + Self::Target: Clone, { self.read().clone() } /// Run a function with a reference to the value. If the value has been dropped, this will panic. #[track_caller] - fn with(&self, f: impl FnOnce(&T) -> O) -> O { + fn with(&self, f: impl FnOnce(&Self::Target) -> O) -> O { f(&*self.read()) } /// Run a function with a reference to the value. If the value has been dropped, this will panic. #[track_caller] - fn with_peek(&self, f: impl FnOnce(&T) -> O) -> O { + fn with_peek(&self, f: impl FnOnce(&Self::Target) -> O) -> O { f(&*self.peek()) } /// Index into the inner value and return a reference to the result. If the value has been dropped or the index is invalid, this will panic. #[track_caller] - fn index(&self, index: I) -> Self::Ref + fn index(&self, index: I) -> Self::Ref<>::Output> where - T: std::ops::Index, + Self::Target: std::ops::Index, { Self::map_ref(self.read(), |v| v.index(index)) } #[doc(hidden)] - fn deref_impl<'a>(&self) -> &'a dyn Fn() -> T + fn deref_impl<'a>(&self) -> &'a dyn Fn() -> Self::Target where Self: Sized + 'a, - T: Clone, + Self::Target: Clone, { // https://github.com/dtolnay/case-studies/tree/master/callable-types @@ -92,7 +99,7 @@ pub trait Readable { } /// An extension trait for Readable> that provides some convenience methods. -pub trait ReadableVecExt: Readable> { +pub trait ReadableVecExt: Readable> { /// Returns the length of the inner vector. #[track_caller] fn len(&self) -> usize { @@ -144,7 +151,7 @@ pub struct ReadableValueIterator<'a, T, R> { phantom: std::marker::PhantomData, } -impl<'a, T: 'static, R: Readable>> Iterator for ReadableValueIterator<'a, T, R> { +impl<'a, T: 'static, R: Readable>> Iterator for ReadableValueIterator<'a, T, R> { type Item = R::Ref; fn next(&mut self) -> Option { @@ -157,12 +164,12 @@ impl<'a, T: 'static, R: Readable>> Iterator for ReadableValueIterator<'a, impl ReadableVecExt for R where T: 'static, - R: Readable>, + R: Readable>, { } /// An extension trait for Readable> that provides some convenience methods. -pub trait ReadableOptionExt: Readable> { +pub trait ReadableOptionExt: Readable> { /// Unwraps the inner value and clones it. #[track_caller] fn unwrap(&self) -> T @@ -182,6 +189,6 @@ pub trait ReadableOptionExt: Readable> { impl ReadableOptionExt for R where T: 'static, - R: Readable>, + R: Readable>, { } diff --git a/packages/signals/src/read_only_signal.rs b/packages/signals/src/read_only_signal.rs index 8b75d095b..e4ba84945 100644 --- a/packages/signals/src/read_only_signal.rs +++ b/packages/signals/src/read_only_signal.rs @@ -54,14 +54,18 @@ impl>> ReadOnlySignal { } } -impl>> Readable for ReadOnlySignal { +impl>> Readable for ReadOnlySignal { + type Target = T; type Ref = S::Ref; - fn map_ref &U>(ref_: Self::Ref, f: F) -> Self::Ref { + fn map_ref &U>( + ref_: Self::Ref, + f: F, + ) -> Self::Ref { S::map(ref_, f) } - fn try_map_ref Option<&U>>( + fn try_map_ref Option<&U>>( ref_: Self::Ref, f: F, ) -> Option> { diff --git a/packages/signals/src/signal.rs b/packages/signals/src/signal.rs index a35360695..36ebefa91 100644 --- a/packages/signals/src/signal.rs +++ b/packages/signals/src/signal.rs @@ -189,7 +189,8 @@ impl>> Signal { /// Map the signal to a new type. pub fn map(self, f: impl Fn(&T) -> &O + 'static) -> MappedSignal> { - MappedSignal::new(self, f) + // MappedSignal::new(self, f) + todo!() } /// Get the generational id of the signal. @@ -198,14 +199,18 @@ impl>> Signal { } } -impl>> Readable for Signal { +impl>> Readable for Signal { + type Target = T; type Ref = S::Ref; - fn map_ref &U>(ref_: Self::Ref, f: F) -> Self::Ref { + fn map_ref &U>( + ref_: Self::Ref, + f: F, + ) -> Self::Ref { S::map(ref_, f) } - fn try_map_ref Option<&U>>( + fn try_map_ref Option<&U>>( ref_: Self::Ref, f: F, ) -> Option> { @@ -231,17 +236,21 @@ impl>> Readable for Signal { } } -impl>> Writable for Signal { +impl>> Writable for Signal { type Mut = Write; - fn map_mut &mut U>( + fn map_mut &mut U>( ref_: Self::Mut, f: F, ) -> Self::Mut { Write::map(ref_, f) } - fn try_map_mut Option<&mut U>>( + fn try_map_mut< + I: ?Sized + 'static, + U: ?Sized + 'static, + F: FnOnce(&mut I) -> Option<&mut U>, + >( ref_: Self::Mut, f: F, ) -> Option> { diff --git a/packages/signals/src/write.rs b/packages/signals/src/write.rs index 02ab44c82..8866eac96 100644 --- a/packages/signals/src/write.rs +++ b/packages/signals/src/write.rs @@ -1,40 +1,46 @@ use std::ops::DerefMut; +use std::ops::IndexMut; use crate::read::Readable; /// A trait for states that can be read from like [`crate::Signal`], or [`crate::GlobalSignal`]. You may choose to accept this trait as a parameter instead of the concrete type to allow for more flexibility in your API. For example, instead of creating two functions, one that accepts a [`crate::Signal`] and one that accepts a [`crate::GlobalSignal`], you can create one function that accepts a [`Writable`] type. -pub trait Writable: Readable { +pub trait Writable: Readable { /// The type of the reference. type Mut: DerefMut; /// Map the reference to a new type. - fn map_mut &mut U>(ref_: Self::Mut, f: F) - -> Self::Mut; + fn map_mut &mut U>( + ref_: Self::Mut, + f: F, + ) -> Self::Mut; /// Try to map the reference to a new type. - fn try_map_mut Option<&mut U>>( + fn try_map_mut Option<&mut U>>( ref_: Self::Mut, f: F, ) -> Option>; /// Get a mutable reference to the value. If the value has been dropped, this will panic. #[track_caller] - fn write(&mut self) -> Self::Mut { + fn write(&mut self) -> Self::Mut { self.try_write().unwrap() } /// Try to get a mutable reference to the value. If the value has been dropped, this will panic. - fn try_write(&self) -> Result, generational_box::BorrowMutError>; + fn try_write(&self) -> Result, generational_box::BorrowMutError>; /// Run a function with a mutable reference to the value. If the value has been dropped, this will panic. #[track_caller] - fn with_mut(&mut self, f: impl FnOnce(&mut T) -> O) -> O { + fn with_mut(&mut self, f: impl FnOnce(&mut Self::Target) -> O) -> O { f(&mut *self.write()) } /// Set the value of the signal. This will trigger an update on all subscribers. #[track_caller] - fn set(&mut self, value: T) { + fn set(&mut self, value: Self::Target) + where + Self::Target: Sized, + { *self.write() = value; } @@ -42,38 +48,41 @@ pub trait Writable: Readable { #[track_caller] fn toggle(&mut self) where - T: std::ops::Not + Clone, + Self::Target: std::ops::Not + Clone, { self.set(!self.cloned()); } /// Index into the inner value and return a reference to the result. #[track_caller] - fn index_mut(&mut self, index: I) -> Self::Mut + fn index_mut(&mut self, index: I) -> Self::Mut<>::Output> where - T: std::ops::IndexMut, + Self::Target: std::ops::IndexMut, { Self::map_mut(self.write(), |v| v.index_mut(index)) } /// Takes the value out of the Signal, leaving a Default in its place. #[track_caller] - fn take(&mut self) -> T + fn take(&mut self) -> Self::Target where - T: Default, + Self::Target: Default, { self.with_mut(|v| std::mem::take(v)) } /// Replace the value in the Signal, returning the old value. #[track_caller] - fn replace(&mut self, value: T) -> T { + fn replace(&mut self, value: Self::Target) -> Self::Target + where + Self::Target: Sized, + { self.with_mut(|v| std::mem::replace(v, value)) } } /// An extension trait for Writable> that provides some convenience methods. -pub trait WritableOptionExt: Writable> { +pub trait WritableOptionExt: Writable> { /// Gets the value out of the Option, or inserts the given value if the Option is empty. fn get_or_insert(&mut self, default: T) -> Self::Mut { self.get_or_insert_with(|| default) @@ -101,12 +110,12 @@ pub trait WritableOptionExt: Writable> { impl WritableOptionExt for W where T: 'static, - W: Writable>, + W: Writable>, { } /// An extension trait for Writable> that provides some convenience methods. -pub trait WritableVecExt: Writable> { +pub trait WritableVecExt: Writable> { /// Pushes a new value to the end of the vector. #[track_caller] fn push(&mut self, value: T) { @@ -194,7 +203,7 @@ pub struct WritableValueIterator { phantom: std::marker::PhantomData, } -impl>> Iterator for WritableValueIterator { +impl>> Iterator for WritableValueIterator { type Item = R::Mut; fn next(&mut self) -> Option { @@ -207,6 +216,6 @@ impl>> Iterator for WritableValueIterator { impl WritableVecExt for W where T: 'static, - W: Writable>, + W: Writable>, { } From c8937cb4df0213ec6eb2caf6332986146a3fcb6f Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Wed, 7 Feb 2024 09:35:06 -0600 Subject: [PATCH 09/43] make mapped signal readable --- packages/signals/Cargo.toml | 2 +- packages/signals/examples/map_signal.rs | 51 +++++++ packages/signals/src/global/signal.rs | 15 +- packages/signals/src/impls.rs | 18 ++- packages/signals/src/map.rs | 174 ++++++++++++------------ packages/signals/src/read.rs | 20 ++- packages/signals/src/signal.rs | 10 +- packages/signals/src/write.rs | 12 +- 8 files changed, 176 insertions(+), 126 deletions(-) create mode 100644 packages/signals/examples/map_signal.rs diff --git a/packages/signals/Cargo.toml b/packages/signals/Cargo.toml index 8dc9da3af..e13da5dc0 100644 --- a/packages/signals/Cargo.toml +++ b/packages/signals/Cargo.toml @@ -25,7 +25,7 @@ futures-util = { workspace = true } flume = { version = "0.11.0", default-features = false, features = ["async"] } [dev-dependencies] -dioxus = { workspace = true } +dioxus = { workspace = true, features = ["desktop"]} # dioxus-desktop = { workspace = true } tokio = { version = "1", features = ["full"] } tracing-subscriber = "0.3.17" diff --git a/packages/signals/examples/map_signal.rs b/packages/signals/examples/map_signal.rs new file mode 100644 index 000000000..a48886445 --- /dev/null +++ b/packages/signals/examples/map_signal.rs @@ -0,0 +1,51 @@ +#![allow(non_snake_case)] + +use dioxus::prelude::*; +use dioxus_signals::Signal; + +fn main() { + launch(app); +} + +fn app() -> Element { + let mut vec = use_signal(|| vec![0]); + + rsx! { + button { + onclick: move |_| { + let mut write = vec.write(); + let len = write.len() as i32; + write.push(len); + }, + "Create" + } + + button { + onclick: move |_| { + vec.write().pop(); + }, + "Destroy" + } + + for i in 0..vec.len() { + Child { count: vec.map(move |v| &v[i]) } + } + } +} + +#[component] +fn Child(count: MappedSignal>>) -> Element { + use_memo({ + to_owned![count]; + move || { + let value = count.read(); + print!("Child value: {value}"); + } + }); + + rsx! { + div { + "Child: {count}" + } + } +} diff --git a/packages/signals/src/global/signal.rs b/packages/signals/src/global/signal.rs index 99ef1d5e6..e00a41fde 100644 --- a/packages/signals/src/global/signal.rs +++ b/packages/signals/src/global/signal.rs @@ -2,11 +2,11 @@ use crate::read::Readable; use crate::write::Writable; use crate::Write; use dioxus_core::prelude::{IntoAttributeValue, ScopeId}; -use generational_box::{AnyStorage, GenerationalRef, UnsyncStorage}; -use std::{cell::Ref, mem::MaybeUninit, ops::Deref}; +use generational_box::{AnyStorage, UnsyncStorage}; +use std::{mem::MaybeUninit, ops::Deref}; use super::get_global_context; -use crate::{MappedSignal, Signal}; +use crate::Signal; /// A signal that can be accessed from anywhere in the application and created in a static pub struct GlobalSignal { @@ -60,15 +60,6 @@ impl GlobalSignal { self.signal().with_mut(f) } - /// Map the signal to a new type. - pub fn map( - &self, - f: impl Fn(&T) -> &O + 'static, - ) -> MappedSignal>> { - // MappedSignal::new(self.signal(), f) - todo!() - } - /// Get the generational id of the signal. pub fn id(&self) -> generational_box::GenerationalBoxId { self.signal().id() diff --git a/packages/signals/src/impls.rs b/packages/signals/src/impls.rs index 7f5f2b8f6..0fd843e50 100644 --- a/packages/signals/src/impls.rs +++ b/packages/signals/src/impls.rs @@ -2,7 +2,7 @@ use crate::copy_value::CopyValue; use crate::read::Readable; use crate::signal::Signal; use crate::write::Writable; -use crate::{GlobalMemo, GlobalSignal, ReadOnlySignal, SignalData}; +use crate::{GlobalMemo, GlobalSignal, MappedSignal, ReadOnlySignal, SignalData}; use generational_box::Storage; use std::{ @@ -10,7 +10,7 @@ use std::{ ops::{Add, Div, Mul, Sub}, }; -macro_rules! read_impls { +macro_rules! default_impl { ($ty:ident $(: $extra_bounds:path)? $(, $bound_ty:ident : $bound:path, $vec_bound_ty:ident : $vec_bound:path)?) => { $( impl Default for $ty { @@ -20,7 +20,11 @@ macro_rules! read_impls { } } )? + } +} +macro_rules! read_impls { + ($ty:ident $(: $extra_bounds:path)? $(, $bound_ty:ident : $bound:path, $vec_bound_ty:ident : $vec_bound:path)?) => { impl Display for $ty { #[track_caller] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -113,6 +117,7 @@ macro_rules! write_impls { } read_impls!(CopyValue, S: Storage, S: Storage>); +default_impl!(CopyValue, S: Storage, S: Storage>); write_impls!(CopyValue, Storage, Storage>); impl> Clone for CopyValue { @@ -124,6 +129,7 @@ impl> Clone for CopyValue { impl> Copy for CopyValue {} read_impls!(Signal, S: Storage>, S: Storage>>); +default_impl!(Signal, S: Storage>, S: Storage>>); write_impls!(Signal, Storage>, Storage>>); impl>> Clone for Signal { @@ -139,6 +145,11 @@ read_impls!( S: Storage>, S: Storage>> ); +default_impl!( + ReadOnlySignal, + S: Storage>, + S: Storage>> +); impl>> Clone for ReadOnlySignal { fn clone(&self) -> Self { @@ -149,5 +160,8 @@ impl>> Clone for ReadOnlySignal { impl>> Copy for ReadOnlySignal {} read_impls!(GlobalSignal); +default_impl!(GlobalSignal); read_impls!(GlobalMemo: PartialEq); + +read_impls!(MappedSignal, S: Readable, S: Readable); diff --git a/packages/signals/src/map.rs b/packages/signals/src/map.rs index b23d82ef8..152e9eb17 100644 --- a/packages/signals/src/map.rs +++ b/packages/signals/src/map.rs @@ -1,107 +1,101 @@ +use std::{ops::Deref, rc::Rc}; + use crate::read::Readable; -use crate::CopyValue; -use crate::Signal; -use crate::SignalData; -use dioxus_core::ScopeId; -use generational_box::AnyStorage; -use generational_box::Storage; -use generational_box::UnsyncStorage; -use std::fmt::Debug; -use std::fmt::Display; +use dioxus_core::prelude::*; /// A read only signal that has been mapped to a new type. -pub struct MappedSignal { - mapping: CopyValue S::Ref>>, +pub struct MappedSignal { + readable: R, + mapping: Rc &O + 'static>, } -impl MappedSignal<()> { - /// Create a new mapped signal. - pub fn new(readable: R, mapping: impl Fn(&T) -> &U + 'static) -> MappedSignal - where - S: Storage>, - U: ?Sized, - { - todo!() - // MappedSignal { - // mapping: CopyValue::new(Box::new(move || S::map(signal.read(), &mapping))), - // } +impl Clone for MappedSignal { + fn clone(&self) -> Self { + MappedSignal { + readable: self.readable.clone(), + mapping: self.mapping.clone(), + } } } -// impl MappedSignal { -// /// Get the current value of the signal. This will subscribe the current scope to the signal. -// pub fn read(&self) -> U { -// (self.mapping.read())() -// } +impl MappedSignal +where + O: ?Sized, + R: Readable + 'static, +{ + /// Create a new mapped signal. + pub(crate) fn new(readable: R, mapping: impl Fn(&R::Target) -> &O + 'static) -> Self { + MappedSignal { + readable, + mapping: Rc::new(mapping), + } + } +} -// /// Run a closure with a reference to the signal's value. -// pub fn with(&self, f: impl FnOnce(U) -> O) -> O { -// f(self.read()) -// } -// } +impl Readable for MappedSignal +where + O: ?Sized, + R: Readable, +{ + type Target = O; + type Ref = R::Ref; -// impl MappedSignal { -// /// Get the current value of the signal. This will subscribe the current scope to the signal. -// pub fn value(&self) -> U { -// self.read().clone() -// } -// } + fn map_ref &U>( + ref_: Self::Ref, + f: F, + ) -> Self::Ref { + R::map_ref(ref_, f) + } -// impl PartialEq for MappedSignal { -// fn eq(&self, other: &Self) -> bool { -// self.mapping == other.mapping -// } -// } + fn try_map_ref Option<&U>>( + ref_: Self::Ref, + f: F, + ) -> Option> { + R::try_map_ref(ref_, f) + } -// impl std::clone::Clone for MappedSignal { -// fn clone(&self) -> Self { -// *self -// } -// } + fn try_read(&self) -> Result, generational_box::BorrowError> { + self.readable + .try_read() + .map(|ref_| R::map_ref(ref_, |r| (self.mapping)(r))) + } -// impl Copy for MappedSignal {} + fn peek(&self) -> Self::Ref { + R::map_ref(self.readable.peek(), |r| (self.mapping)(r)) + } +} -// impl Display for MappedSignal { -// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -// self.with(|v| Display::fmt(&v, f)) -// } -// } +impl IntoAttributeValue for MappedSignal +where + O: Clone + IntoAttributeValue + ?Sized, + R: Readable + 'static, +{ + fn into_value(self) -> dioxus_core::AttributeValue { + self.with(|f| f.clone().into_value()) + } +} -// impl Debug for MappedSignal { -// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -// self.with(|v| Debug::fmt(&v, f)) -// } -// } +impl PartialEq for MappedSignal +where + O: ?Sized, + R: PartialEq + Readable + 'static, +{ + fn eq(&self, other: &Self) -> bool { + self.readable == other.readable && std::ptr::eq(&self.mapping, &other.mapping) + } +} -// impl std::ops::Deref for MappedSignal { -// type Target = dyn Fn() -> T; +/// Allow calling a signal with signal() syntax +/// +/// Currently only limited to copy types, though could probably specialize for string/arc/rc +impl Deref for MappedSignal +where + O: Clone, + R: Readable + 'static, +{ + type Target = dyn Fn() -> O; -// fn deref(&self) -> &Self::Target { -// // https://github.com/dtolnay/case-studies/tree/master/callable-types - -// // First we create a closure that captures something with the Same in memory layout as Self (MaybeUninit). -// let uninit_callable = std::mem::MaybeUninit::::uninit(); -// // Then move that value into the closure. We assume that the closure now has a in memory layout of Self. -// let uninit_closure = move || Self::read(unsafe { &*uninit_callable.as_ptr() }); - -// // Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure. -// let size_of_closure = std::mem::size_of_val(&uninit_closure); -// assert_eq!(size_of_closure, std::mem::size_of::()); - -// // Then cast the lifetime of the closure to the lifetime of &self. -// fn cast_lifetime<'a, T>(_a: &T, b: &'a T) -> &'a T { -// b -// } -// let reference_to_closure = cast_lifetime( -// { -// // The real closure that we will never use. -// &uninit_closure -// }, -// // We transmute self into a reference to the closure. This is safe because we know that the closure has the same memory layout as Self so &Closure == &Self. -// unsafe { std::mem::transmute(self) }, -// ); - -// // Cast the closure to a trait object. -// reference_to_closure as &Self::Target -// } -// } + fn deref(&self) -> &Self::Target { + Readable::deref_impl(self) + } +} diff --git a/packages/signals/src/read.rs b/packages/signals/src/read.rs index c54095769..12a4bdfa8 100644 --- a/packages/signals/src/read.rs +++ b/packages/signals/src/read.rs @@ -3,13 +3,15 @@ use std::{ ops::{Deref, Index}, }; +use crate::MappedSignal; + /// A trait for states that can be read from like [`crate::Signal`], [`crate::GlobalSignal`], or [`crate::ReadOnlySignal`]. You may choose to accept this trait as a parameter instead of the concrete type to allow for more flexibility in your API. For example, instead of creating two functions, one that accepts a [`crate::Signal`] and one that accepts a [`crate::GlobalSignal`], you can create one function that accepts a [`Readable`] type. pub trait Readable { /// The target type of the reference. type Target: ?Sized + 'static; /// The type of the reference. - type Ref: Deref; + type Ref: Deref + 'static; /// Map the reference to a new type. fn map_ref &U>(ref_: Self::Ref, f: F) @@ -24,6 +26,14 @@ pub trait Readable { /// Try to get the current value of the state. If this is a signal, this will subscribe the current scope to the signal. If the value has been dropped, this will panic. fn try_read(&self) -> Result, generational_box::BorrowError>; + /// Map the readable type to a new type. + fn map(self, f: impl Fn(&Self::Target) -> &O + 'static) -> MappedSignal + where + Self: Sized + 'static, + { + MappedSignal::new(self, f) + } + /// Get the current value of the state. If this is a signal, this will subscribe the current scope to the signal. If the value has been dropped, this will panic. #[track_caller] fn read(&self) -> Self::Ref { @@ -132,26 +142,24 @@ pub trait ReadableVecExt: Readable> { /// Get an iterator over the values of the inner vector. #[track_caller] - fn iter(&self) -> ReadableValueIterator<'_, T, Self> + fn iter(&self) -> ReadableValueIterator<'_, Self> where Self: Sized, { ReadableValueIterator { index: 0, value: self, - phantom: std::marker::PhantomData, } } } /// An iterator over the values of a `Readable>`. -pub struct ReadableValueIterator<'a, T, R> { +pub struct ReadableValueIterator<'a, R> { index: usize, value: &'a R, - phantom: std::marker::PhantomData, } -impl<'a, T: 'static, R: Readable>> Iterator for ReadableValueIterator<'a, T, R> { +impl<'a, T: 'static, R: Readable>> Iterator for ReadableValueIterator<'a, R> { type Item = R::Ref; fn next(&mut self) -> Option { diff --git a/packages/signals/src/signal.rs b/packages/signals/src/signal.rs index 36ebefa91..14233307c 100644 --- a/packages/signals/src/signal.rs +++ b/packages/signals/src/signal.rs @@ -1,6 +1,6 @@ use crate::{ - read::Readable, write::Writable, CopyValue, GlobalMemo, GlobalSignal, MappedSignal, - ReactiveContext, ReadOnlySignal, + read::Readable, write::Writable, CopyValue, GlobalMemo, GlobalSignal, ReactiveContext, + ReadOnlySignal, }; use dioxus_core::{ prelude::{flush_sync, spawn, IntoAttributeValue}, @@ -187,12 +187,6 @@ impl>> Signal { } } - /// Map the signal to a new type. - pub fn map(self, f: impl Fn(&T) -> &O + 'static) -> MappedSignal> { - // MappedSignal::new(self, f) - todo!() - } - /// Get the generational id of the signal. pub fn id(&self) -> generational_box::GenerationalBoxId { self.inner.id() diff --git a/packages/signals/src/write.rs b/packages/signals/src/write.rs index 8866eac96..4cba48c62 100644 --- a/packages/signals/src/write.rs +++ b/packages/signals/src/write.rs @@ -6,7 +6,7 @@ use crate::read::Readable; /// A trait for states that can be read from like [`crate::Signal`], or [`crate::GlobalSignal`]. You may choose to accept this trait as a parameter instead of the concrete type to allow for more flexibility in your API. For example, instead of creating two functions, one that accepts a [`crate::Signal`] and one that accepts a [`crate::GlobalSignal`], you can create one function that accepts a [`Writable`] type. pub trait Writable: Readable { /// The type of the reference. - type Mut: DerefMut; + type Mut: DerefMut + 'static; /// Map the reference to a new type. fn map_mut &mut U>( @@ -68,7 +68,7 @@ pub trait Writable: Readable { where Self::Target: Default, { - self.with_mut(|v| std::mem::take(v)) + self.with_mut(std::mem::take) } /// Replace the value in the Signal, returning the old value. @@ -184,26 +184,24 @@ pub trait WritableVecExt: Writable> { /// Gets an iterator over the values of the vector. #[track_caller] - fn iter_mut(&self) -> WritableValueIterator + fn iter_mut(&self) -> WritableValueIterator where Self: Sized + Clone, { WritableValueIterator { index: 0, value: self.clone(), - phantom: std::marker::PhantomData, } } } /// An iterator over the values of a `Writable>`. -pub struct WritableValueIterator { +pub struct WritableValueIterator { index: usize, value: R, - phantom: std::marker::PhantomData, } -impl>> Iterator for WritableValueIterator { +impl>> Iterator for WritableValueIterator { type Item = R::Mut; fn next(&mut self) -> Option { From 8689509eb56239784cd9b62cef62e4579c2c8213 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Wed, 7 Feb 2024 11:19:39 -0600 Subject: [PATCH 10/43] erase the original readable type --- packages/signals/examples/map_signal.rs | 5 +- packages/signals/src/copy_value.rs | 21 ++----- packages/signals/src/global/memo.rs | 24 ++----- packages/signals/src/global/signal.rs | 24 ++----- packages/signals/src/impls.rs | 4 +- packages/signals/src/map.rs | 75 +++++++++------------- packages/signals/src/read.rs | 79 +++++++++++++----------- packages/signals/src/read_only_signal.rs | 20 +----- packages/signals/src/signal.rs | 22 ++----- 9 files changed, 99 insertions(+), 175 deletions(-) diff --git a/packages/signals/examples/map_signal.rs b/packages/signals/examples/map_signal.rs index a48886445..71d882638 100644 --- a/packages/signals/examples/map_signal.rs +++ b/packages/signals/examples/map_signal.rs @@ -1,7 +1,6 @@ #![allow(non_snake_case)] use dioxus::prelude::*; -use dioxus_signals::Signal; fn main() { launch(app); @@ -34,12 +33,12 @@ fn app() -> Element { } #[component] -fn Child(count: MappedSignal>>) -> Element { +fn Child(count: MappedSignal) -> Element { use_memo({ to_owned![count]; move || { let value = count.read(); - print!("Child value: {value}"); + println!("Child value: {value}"); } }); diff --git a/packages/signals/src/copy_value.rs b/packages/signals/src/copy_value.rs index bf52d090c..4961fb2b8 100644 --- a/packages/signals/src/copy_value.rs +++ b/packages/signals/src/copy_value.rs @@ -13,6 +13,7 @@ use dioxus_core::ScopeId; use generational_box::{GenerationalBox, Owner, Storage}; +use crate::ReadableRef; use crate::Writable; use crate::{ReactiveContext, Readable}; @@ -206,27 +207,13 @@ impl> CopyValue { impl> Readable for CopyValue { type Target = T; - type Ref = S::Ref; + type Storage = S; - fn map_ref &U>( - ref_: Self::Ref, - f: F, - ) -> Self::Ref { - S::map(ref_, f) - } - - fn try_map_ref Option<&U>>( - ref_: Self::Ref, - f: F, - ) -> Option> { - S::try_map(ref_, f) - } - - fn try_read(&self) -> Result, generational_box::BorrowError> { + fn try_read(&self) -> Result, generational_box::BorrowError> { self.value.try_read() } - fn peek(&self) -> Self::Ref { + fn peek(&self) -> ReadableRef { self.value.read() } } diff --git a/packages/signals/src/global/memo.rs b/packages/signals/src/global/memo.rs index 6ab7c3738..9bea70da1 100644 --- a/packages/signals/src/global/memo.rs +++ b/packages/signals/src/global/memo.rs @@ -1,6 +1,6 @@ -use crate::read::Readable; +use crate::{read::Readable, ReadableRef}; use dioxus_core::prelude::{IntoAttributeValue, ScopeId}; -use generational_box::{AnyStorage, UnsyncStorage}; +use generational_box::UnsyncStorage; use std::{mem::MaybeUninit, ops::Deref}; use crate::{ReadOnlySignal, Signal}; @@ -53,29 +53,15 @@ impl GlobalMemo { impl Readable for GlobalMemo { type Target = T; - type Ref = generational_box::GenerationalRef>; - - fn map_ref &U>( - ref_: Self::Ref, - f: F, - ) -> Self::Ref { - ::map(ref_, f) - } - - fn try_map_ref Option<&U>>( - ref_: Self::Ref, - f: F, - ) -> Option> { - ::try_map(ref_, f) - } + type Storage = UnsyncStorage; #[track_caller] - fn try_read(&self) -> Result, generational_box::BorrowError> { + fn try_read(&self) -> Result, generational_box::BorrowError> { self.signal().try_read() } #[track_caller] - fn peek(&self) -> Self::Ref { + fn peek(&self) -> ReadableRef { self.signal().peek() } } diff --git a/packages/signals/src/global/signal.rs b/packages/signals/src/global/signal.rs index e00a41fde..dda337232 100644 --- a/packages/signals/src/global/signal.rs +++ b/packages/signals/src/global/signal.rs @@ -1,8 +1,8 @@ -use crate::read::Readable; use crate::write::Writable; use crate::Write; +use crate::{read::Readable, ReadableRef}; use dioxus_core::prelude::{IntoAttributeValue, ScopeId}; -use generational_box::{AnyStorage, UnsyncStorage}; +use generational_box::UnsyncStorage; use std::{mem::MaybeUninit, ops::Deref}; use super::get_global_context; @@ -68,29 +68,15 @@ impl GlobalSignal { impl Readable for GlobalSignal { type Target = T; - type Ref = generational_box::GenerationalRef>; - - fn map_ref &U>( - ref_: Self::Ref, - f: F, - ) -> Self::Ref { - ::map(ref_, f) - } - - fn try_map_ref Option<&U>>( - ref_: Self::Ref, - f: F, - ) -> Option> { - ::try_map(ref_, f) - } + type Storage = UnsyncStorage; #[track_caller] - fn try_read(&self) -> Result, generational_box::BorrowError> { + fn try_read(&self) -> Result, generational_box::BorrowError> { self.signal().try_read() } #[track_caller] - fn peek(&self) -> Self::Ref { + fn peek(&self) -> ReadableRef { self.signal().peek() } } diff --git a/packages/signals/src/impls.rs b/packages/signals/src/impls.rs index 0fd843e50..3d120b54e 100644 --- a/packages/signals/src/impls.rs +++ b/packages/signals/src/impls.rs @@ -3,7 +3,7 @@ use crate::read::Readable; use crate::signal::Signal; use crate::write::Writable; use crate::{GlobalMemo, GlobalSignal, MappedSignal, ReadOnlySignal, SignalData}; -use generational_box::Storage; +use generational_box::{AnyStorage, Storage}; use std::{ fmt::{Debug, Display}, @@ -164,4 +164,4 @@ default_impl!(GlobalSignal); read_impls!(GlobalMemo: PartialEq); -read_impls!(MappedSignal, S: Readable, S: Readable); +read_impls!(MappedSignal, S: AnyStorage, S: AnyStorage); diff --git a/packages/signals/src/map.rs b/packages/signals/src/map.rs index 152e9eb17..e203a6d0e 100644 --- a/packages/signals/src/map.rs +++ b/packages/signals/src/map.rs @@ -1,97 +1,82 @@ use std::{ops::Deref, rc::Rc}; -use crate::read::Readable; +use crate::{read::Readable, ReadableRef}; use dioxus_core::prelude::*; +use generational_box::{AnyStorage, UnsyncStorage}; /// A read only signal that has been mapped to a new type. -pub struct MappedSignal { - readable: R, - mapping: Rc &O + 'static>, +pub struct MappedSignal { + try_read: Rc Result, generational_box::BorrowError> + 'static>, + peek: Rc S::Ref + 'static>, } -impl Clone for MappedSignal { +impl Clone for MappedSignal { fn clone(&self) -> Self { MappedSignal { - readable: self.readable.clone(), - mapping: self.mapping.clone(), + try_read: self.try_read.clone(), + peek: self.peek.clone(), } } } -impl MappedSignal +impl MappedSignal where O: ?Sized, - R: Readable + 'static, + S: AnyStorage, { /// Create a new mapped signal. - pub(crate) fn new(readable: R, mapping: impl Fn(&R::Target) -> &O + 'static) -> Self { - MappedSignal { - readable, - mapping: Rc::new(mapping), - } + pub(crate) fn new( + try_read: Rc Result, generational_box::BorrowError> + 'static>, + peek: Rc S::Ref + 'static>, + ) -> Self { + MappedSignal { try_read, peek } } } -impl Readable for MappedSignal +impl Readable for MappedSignal where O: ?Sized, - R: Readable, + S: AnyStorage, { type Target = O; - type Ref = R::Ref; + type Storage = S; - fn map_ref &U>( - ref_: Self::Ref, - f: F, - ) -> Self::Ref { - R::map_ref(ref_, f) + fn try_read(&self) -> Result, generational_box::BorrowError> { + (self.try_read)() } - fn try_map_ref Option<&U>>( - ref_: Self::Ref, - f: F, - ) -> Option> { - R::try_map_ref(ref_, f) - } - - fn try_read(&self) -> Result, generational_box::BorrowError> { - self.readable - .try_read() - .map(|ref_| R::map_ref(ref_, |r| (self.mapping)(r))) - } - - fn peek(&self) -> Self::Ref { - R::map_ref(self.readable.peek(), |r| (self.mapping)(r)) + fn peek(&self) -> ReadableRef { + (self.peek)() } } -impl IntoAttributeValue for MappedSignal +impl IntoAttributeValue for MappedSignal where - O: Clone + IntoAttributeValue + ?Sized, - R: Readable + 'static, + O: Clone + IntoAttributeValue, + S: AnyStorage, { fn into_value(self) -> dioxus_core::AttributeValue { self.with(|f| f.clone().into_value()) } } -impl PartialEq for MappedSignal +impl PartialEq for MappedSignal where O: ?Sized, - R: PartialEq + Readable + 'static, + S: AnyStorage, { fn eq(&self, other: &Self) -> bool { - self.readable == other.readable && std::ptr::eq(&self.mapping, &other.mapping) + std::ptr::eq(&self.peek, &other.peek) && std::ptr::eq(&self.try_read, &other.try_read) } } /// Allow calling a signal with signal() syntax /// /// Currently only limited to copy types, though could probably specialize for string/arc/rc -impl Deref for MappedSignal +impl Deref for MappedSignal where O: Clone, - R: Readable + 'static, + S: AnyStorage + 'static, { type Target = dyn Fn() -> O; diff --git a/packages/signals/src/read.rs b/packages/signals/src/read.rs index 12a4bdfa8..63de45047 100644 --- a/packages/signals/src/read.rs +++ b/packages/signals/src/read.rs @@ -1,47 +1,56 @@ -use std::{ - mem::MaybeUninit, - ops::{Deref, Index}, -}; +use std::{mem::MaybeUninit, ops::Index, rc::Rc}; + +use generational_box::AnyStorage; use crate::MappedSignal; +/// A reference to a value that can be read from. +#[allow(type_alias_bounds)] +pub type ReadableRef::Target> = ::Ref; + /// A trait for states that can be read from like [`crate::Signal`], [`crate::GlobalSignal`], or [`crate::ReadOnlySignal`]. You may choose to accept this trait as a parameter instead of the concrete type to allow for more flexibility in your API. For example, instead of creating two functions, one that accepts a [`crate::Signal`] and one that accepts a [`crate::GlobalSignal`], you can create one function that accepts a [`Readable`] type. pub trait Readable { /// The target type of the reference. type Target: ?Sized + 'static; - /// The type of the reference. - type Ref: Deref + 'static; - - /// Map the reference to a new type. - fn map_ref &U>(ref_: Self::Ref, f: F) - -> Self::Ref; - - /// Try to map the reference to a new type. - fn try_map_ref Option<&U>>( - ref_: Self::Ref, - f: F, - ) -> Option>; - - /// Try to get the current value of the state. If this is a signal, this will subscribe the current scope to the signal. If the value has been dropped, this will panic. - fn try_read(&self) -> Result, generational_box::BorrowError>; + /// The type of the storage this readable uses. + type Storage: AnyStorage; /// Map the readable type to a new type. - fn map(self, f: impl Fn(&Self::Target) -> &O + 'static) -> MappedSignal + fn map(self, f: impl Fn(&Self::Target) -> &O + 'static) -> MappedSignal where - Self: Sized + 'static, + Self: Clone + Sized + 'static, { - MappedSignal::new(self, f) + let mapping = Rc::new(f); + let try_read = Rc::new({ + let self_ = self.clone(); + let mapping = mapping.clone(); + move || { + self_ + .try_read() + .map(|ref_| ::map(ref_, |r| mapping(r))) + } + }) + as Rc< + dyn Fn() -> Result, generational_box::BorrowError> + 'static, + >; + let peek = Rc::new(move || ::map(self.peek(), |r| mapping(r))) + as Rc ReadableRef + 'static>; + MappedSignal::new(try_read, peek) } /// Get the current value of the state. If this is a signal, this will subscribe the current scope to the signal. If the value has been dropped, this will panic. #[track_caller] - fn read(&self) -> Self::Ref { + fn read(&self) -> ReadableRef { self.try_read().unwrap() } + /// Try to get the current value of the state. If this is a signal, this will subscribe the current scope to the signal. If the value has been dropped, this will panic. + #[track_caller] + fn try_read(&self) -> Result, generational_box::BorrowError>; + /// Get the current value of the state without subscribing to updates. If the value has been dropped, this will panic. - fn peek(&self) -> Self::Ref; + fn peek(&self) -> ReadableRef; /// Clone the inner value and return it. If the value has been dropped, this will panic. #[track_caller] @@ -66,11 +75,11 @@ pub trait Readable { /// Index into the inner value and return a reference to the result. If the value has been dropped or the index is invalid, this will panic. #[track_caller] - fn index(&self, index: I) -> Self::Ref<>::Output> + fn index(&self, index: I) -> ReadableRef>::Output> where Self::Target: std::ops::Index, { - Self::map_ref(self.read(), |v| v.index(index)) + ::map(self.read(), |v| v.index(index)) } #[doc(hidden)] @@ -124,20 +133,20 @@ pub trait ReadableVecExt: Readable> { /// Get the first element of the inner vector. #[track_caller] - fn first(&self) -> Option> { - Self::try_map_ref(self.read(), |v| v.first()) + fn first(&self) -> Option> { + ::try_map(self.read(), |v| v.first()) } /// Get the last element of the inner vector. #[track_caller] - fn last(&self) -> Option> { - Self::try_map_ref(self.read(), |v| v.last()) + fn last(&self) -> Option> { + ::try_map(self.read(), |v| v.last()) } /// Get the element at the given index of the inner vector. #[track_caller] - fn get(&self, index: usize) -> Option> { - Self::try_map_ref(self.read(), |v| v.get(index)) + fn get(&self, index: usize) -> Option> { + ::try_map(self.read(), |v| v.get(index)) } /// Get an iterator over the values of the inner vector. @@ -160,7 +169,7 @@ pub struct ReadableValueIterator<'a, R> { } impl<'a, T: 'static, R: Readable>> Iterator for ReadableValueIterator<'a, R> { - type Item = R::Ref; + type Item = ReadableRef; fn next(&mut self) -> Option { let index = self.index; @@ -189,8 +198,8 @@ pub trait ReadableOptionExt: Readable> { /// Attempts to read the inner value of the Option. #[track_caller] - fn as_ref(&self) -> Option> { - Self::try_map_ref(self.read(), |v| v.as_ref()) + fn as_ref(&self) -> Option> { + ::try_map(self.read(), |v| v.as_ref()) } } diff --git a/packages/signals/src/read_only_signal.rs b/packages/signals/src/read_only_signal.rs index e4ba84945..54106be31 100644 --- a/packages/signals/src/read_only_signal.rs +++ b/packages/signals/src/read_only_signal.rs @@ -1,4 +1,4 @@ -use crate::{read::Readable, Signal, SignalData}; +use crate::{read::Readable, ReadableRef, Signal, SignalData}; use std::ops::Deref; use dioxus_core::{prelude::IntoAttributeValue, ScopeId}; @@ -56,24 +56,10 @@ impl>> ReadOnlySignal { impl>> Readable for ReadOnlySignal { type Target = T; - type Ref = S::Ref; - - fn map_ref &U>( - ref_: Self::Ref, - f: F, - ) -> Self::Ref { - S::map(ref_, f) - } - - fn try_map_ref Option<&U>>( - ref_: Self::Ref, - f: F, - ) -> Option> { - S::try_map(ref_, f) - } + type Storage = S; #[track_caller] - fn try_read(&self) -> Result, generational_box::BorrowError> { + fn try_read(&self) -> Result, generational_box::BorrowError> { self.inner.try_read() } diff --git a/packages/signals/src/signal.rs b/packages/signals/src/signal.rs index 14233307c..0b11051b1 100644 --- a/packages/signals/src/signal.rs +++ b/packages/signals/src/signal.rs @@ -1,6 +1,6 @@ use crate::{ read::Readable, write::Writable, CopyValue, GlobalMemo, GlobalSignal, ReactiveContext, - ReadOnlySignal, + ReadOnlySignal, ReadableRef, }; use dioxus_core::{ prelude::{flush_sync, spawn, IntoAttributeValue}, @@ -195,24 +195,10 @@ impl>> Signal { impl>> Readable for Signal { type Target = T; - type Ref = S::Ref; - - fn map_ref &U>( - ref_: Self::Ref, - f: F, - ) -> Self::Ref { - S::map(ref_, f) - } - - fn try_map_ref Option<&U>>( - ref_: Self::Ref, - f: F, - ) -> Option> { - S::try_map(ref_, f) - } + type Storage = S; #[track_caller] - fn try_read(&self) -> Result, generational_box::BorrowError> { + fn try_read(&self) -> Result, generational_box::BorrowError> { let inner = self.inner.try_read()?; let reactive_context = ReactiveContext::current(); @@ -224,7 +210,7 @@ impl>> Readable for Signal { /// Get the current value of the signal. **Unlike read, this will not subscribe the current scope to the signal which can cause parts of your UI to not update.** /// /// If the signal has been dropped, this will panic. - fn peek(&self) -> S::Ref { + fn peek(&self) -> ReadableRef { let inner = self.inner.read(); S::map(inner, |v| &v.value) } From 1bbecc3c705a53f491be2a9e1b159f44b42d4203 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Wed, 7 Feb 2024 11:31:13 -0600 Subject: [PATCH 11/43] restore dioxus signals dependencies --- Cargo.lock | 259 +++++++++++++++++------------------- Cargo.toml | 2 +- packages/signals/Cargo.toml | 3 +- 3 files changed, 121 insertions(+), 143 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1f7a0f6e5..5f93476a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -168,9 +168,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" @@ -422,7 +422,7 @@ dependencies = [ "futures-io", "futures-lite 2.2.0", "parking", - "polling 3.3.2", + "polling 3.4.0", "rustix 0.38.31", "slab", "tracing", @@ -907,16 +907,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -dependencies = [ - "byteorder", - "safemem", -] - [[package]] name = "base64" version = "0.13.1" @@ -1158,9 +1148,9 @@ checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytecheck" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" dependencies = [ "bytecheck_derive", "ptr_meta", @@ -1169,9 +1159,9 @@ dependencies = [ [[package]] name = "bytecheck_derive" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" dependencies = [ "proc-macro2", "quote", @@ -1180,9 +1170,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.14.1" +version = "1.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9" +checksum = "ea31d69bda4949c1c1562c1e6f042a1caefac98cdc8a298260a2ff41c1e2d42b" [[package]] name = "byteorder" @@ -1287,7 +1277,7 @@ dependencies = [ "serde", "tempfile", "thiserror", - "toml 0.8.9", + "toml 0.8.10", "walkdir", ] @@ -1374,7 +1364,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3f9629bc6c4388ea699781dc988c2b99766d7679b151c81990b4fa1208fafd3" dependencies = [ "serde", - "toml 0.8.9", + "toml 0.8.10", ] [[package]] @@ -1384,7 +1374,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "802b755090e39835a4b0440fb0bbee0df7495a8b337f63db21e616f7821c7e8c" dependencies = [ "serde", - "toml 0.8.9", + "toml 0.8.10", ] [[package]] @@ -2438,7 +2428,7 @@ dependencies = [ "tempfile", "thiserror", "tokio", - "toml 0.8.9", + "toml 0.8.10", "toml_edit 0.21.1", "tower", "tower-http 0.2.5", @@ -2885,7 +2875,7 @@ version = "0.4.3" dependencies = [ "dioxus", "dioxus-core", - "flume 0.11.0", + "flume", "futures-channel", "futures-util", "generational-box", @@ -3299,12 +3289,12 @@ checksum = "de853764b47027c2e862a995c34978ffa63c1501f2e15f987ba11bd4f9bba193" [[package]] name = "exr" -version = "1.6.4" +version = "1.72.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279d3efcc55e19917fff7ab3ddd6c14afb6a90881a0078465196fe2f99d08c56" +checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" dependencies = [ "bit_field", - "flume 0.10.14", + "flume", "half 2.3.1", "lebe", "miniz_oxide", @@ -3381,7 +3371,7 @@ dependencies = [ "atomic 0.6.0", "pear", "serde", - "toml 0.8.9", + "toml 0.8.10", "uncased", "version_check", ] @@ -3420,19 +3410,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "flume" -version = "0.10.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" -dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "pin-project", - "spin 0.9.8", -] - [[package]] name = "flume" version = "0.11.0" @@ -3927,9 +3904,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.18.1" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf97ba92db08df386e10c8ede66a2a0369bd277090afd8710e19e38de9ec0cd" +checksum = "1b3ba52851e73b46a4c3df1d89343741112003f0f6f13beb0dfac9e457c3fdcd" dependencies = [ "bitflags 2.4.2", "libc", @@ -4687,9 +4664,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" +checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" [[package]] name = "hex" @@ -4954,9 +4931,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.59" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -5225,7 +5202,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.4", + "hermit-abi 0.3.5", "libc", "windows-sys 0.48.0", ] @@ -5281,7 +5258,7 @@ version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" dependencies = [ - "hermit-abi 0.3.4", + "hermit-abi 0.3.5", "rustix 0.38.31", "windows-sys 0.52.0", ] @@ -5298,9 +5275,9 @@ dependencies = [ [[package]] name = "is_ci" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" [[package]] name = "itertools" @@ -5406,9 +5383,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" dependencies = [ "wasm-bindgen", ] @@ -5561,9 +5538,9 @@ dependencies = [ [[package]] name = "libgit2-sys" -version = "0.16.1+1.7.1" +version = "0.16.2+1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2a2bb3680b094add03bb3732ec520ece34da31a8cd2d633d1389d0f0fb60d0c" +checksum = "ee4126d8b4ee5c9d9ea891dd875cfdc1e9d0950437179104b183d7d8a74d24e8" dependencies = [ "cc", "libc", @@ -6120,9 +6097,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", "simd-adler32", @@ -6273,15 +6250,6 @@ dependencies = [ "rand 0.8.5", ] -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom 0.2.12", -] - [[package]] name = "nasm-rs" version = "0.2.5" @@ -6487,9 +6455,9 @@ dependencies = [ [[package]] name = "num-derive" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", @@ -6545,7 +6513,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.4", + "hermit-abi 0.3.5", "libc", ] @@ -6968,9 +6936,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.6" +version = "2.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f200d8d83c44a45b21764d1916299752ca035d15ecd46faca3e9a2a2bf6ad06" +checksum = "219c0dcc30b6a27553f9cc242972b67f75b60eb0db71f0b5462f38b058c41546" dependencies = [ "memchr", "thiserror", @@ -6979,9 +6947,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.6" +version = "2.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcd6ab1236bbdb3a49027e920e693192ebfe8913f6d60e294de57463a493cfde" +checksum = "22e1288dbd7786462961e69bfd4df7848c1e37e8b74303dbdab82c3a9cdd2809" dependencies = [ "pest", "pest_generator", @@ -6989,9 +6957,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.6" +version = "2.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a31940305ffc96863a735bef7c7994a00b325a7138fdbc5bda0f1a0476d3275" +checksum = "1381c29a877c6d34b8c176e734f35d7f7f5b3adaefe940cb4d1bb7af94678e2e" dependencies = [ "pest", "pest_meta", @@ -7002,9 +6970,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.6" +version = "2.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ff62f5259e53b78d1af898941cdcdccfae7385cf7d793a6e55de5d05bb4b7d" +checksum = "d0934d6907f148c22a3acbda520c7eed243ad7487a30f51f6ce52b58b7077a8a" dependencies = [ "once_cell", "pest", @@ -7320,9 +7288,9 @@ dependencies = [ [[package]] name = "polling" -version = "3.3.2" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545c980a3880efd47b2e262f6a4bb6daad6555cf3367aa9c4e52895f69537a41" +checksum = "30054e72317ab98eddd8561db0f6524df3367636884b7b21b703e4b280a84a14" dependencies = [ "cfg-if", "concurrent-queue", @@ -7754,7 +7722,7 @@ dependencies = [ "nasm-rs", "new_debug_unreachable", "noop_proc_macro", - "num-derive 0.4.1", + "num-derive 0.4.2", "num-traits", "once_cell", "paste", @@ -7917,9 +7885,9 @@ dependencies = [ [[package]] name = "rend" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" dependencies = [ "bytecheck", ] @@ -8071,9 +8039,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.7.43" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527a97cdfef66f65998b5f3b637c26f5a5ec09cc52a3f9932313ac645f4190f5" +checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" dependencies = [ "bitvec", "bytecheck", @@ -8089,9 +8057,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.43" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5c462a1328c8e67e4d6dbad1eb0355dd43e8ab432c6e227a43657f16ade5033" +checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" dependencies = [ "proc-macro2", "quote", @@ -9440,7 +9408,7 @@ checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490" dependencies = [ "atoi", "chrono", - "flume 0.11.0", + "flume", "futures-channel", "futures-core", "futures-executor", @@ -9667,7 +9635,7 @@ dependencies = [ "cfg-expr 0.15.6", "heck 0.4.1", "pkg-config", - "toml 0.8.9", + "toml 0.8.10", "version-compare", ] @@ -9939,9 +9907,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe80ced77cbfb4cb91a94bf72b378b4b6791a0d9b7f09d0be747d1bdff4e68bd" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", "itoa 1.0.10", @@ -10158,15 +10126,15 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6a4b9e8023eb94392d3dca65d717c53abc5dad49c07cb65bb8fcd87115fa325" +checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" dependencies = [ "indexmap 2.2.2", "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.21.1", + "toml_edit 0.22.4", ] [[package]] @@ -10207,6 +10175,17 @@ name = "toml_edit" version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.2.2", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ffdf896f8daaabf9b66ba8e77ea1ed5ed0f72821b398aba62352e95062951" dependencies = [ "indexmap 2.2.2", "serde", @@ -10403,9 +10382,9 @@ dependencies = [ [[package]] name = "treediff" -version = "4.0.2" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52984d277bdf2a751072b5df30ec0377febdb02f7696d64c2d7d54630bac4303" +checksum = "4d127780145176e2b5d16611cc25a900150e86e9fd79d3bde6ff3a37359c9cb5" dependencies = [ "serde_json", ] @@ -10564,9 +10543,9 @@ dependencies = [ [[package]] name = "ulid" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3c3b4dcec1e4729aab50688a1a0631483d79e65b194851425e7748287715a6" +checksum = "34778c17965aa2a08913b57e1f34db9b4a63f5de31768b55bf20d2795f921259" dependencies = [ "getrandom 0.2.12", "rand 0.8.5", @@ -10621,9 +10600,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" @@ -10730,7 +10709,7 @@ checksum = "c372e4e6fad129795fb86fda6021b258948560b39883b80ed00510a7d19846b0" dependencies = [ "cfg-if", "noop_proc_macro", - "num-derive 0.4.1", + "num-derive 0.4.2", "num-traits", "profiling", ] @@ -10882,9 +10861,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -10892,9 +10871,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" dependencies = [ "bumpalo", "log", @@ -10907,12 +10886,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-cli-support" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a875870b7b39024cbca8f61a0e1fc8edfe7ac02b484e5a9bcea64374050a850e" +checksum = "806a045c4ec4ef7c3ad86dc27bcb641b84d9eeb3846200f56d7ab0885241d654" dependencies = [ "anyhow", - "base64 0.9.3", + "base64 0.21.7", "log", "rustc-demangle", "serde_json", @@ -10929,9 +10908,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-externref-xform" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04c5d468dc79cfd824d181c386f34c2e7ea521ea5855ddd95af8f4cf3fa676f4" +checksum = "12b6ac5fca1d0992d2328147488169ea166bfe899c88f8ad06cf583f4c492fcf" dependencies = [ "anyhow", "walrus", @@ -10939,9 +10918,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" +checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" dependencies = [ "cfg-if", "js-sys", @@ -10951,9 +10930,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -10961,9 +10940,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", @@ -10974,9 +10953,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-multi-value-xform" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65f10c037dad45759d53b598d4737acdced90a0945023c8c6cd8d67b4b3e4eaf" +checksum = "d1e019acde479e2f090fb7f14a51fa0077ec3a7bb12a56e0e888a82be7b5bd3f" dependencies = [ "anyhow", "walrus", @@ -10984,15 +10963,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" [[package]] name = "wasm-bindgen-test" -version = "0.3.40" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139bd73305d50e1c1c4333210c0db43d989395b64a237bd35c10ef3832a7f70c" +checksum = "143ddeb4f833e2ed0d252e618986e18bfc7b0e52f2d28d77d05b2f045dd8eb61" dependencies = [ "console_error_panic_hook", "js-sys", @@ -11004,9 +10983,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.40" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70072aebfe5da66d2716002c729a14e4aec4da0e23cc2ea66323dac541c93928" +checksum = "a5211b7550606857312bba1d978a8ec75692eae187becc5e680444fffc5e6f89" dependencies = [ "proc-macro2", "quote", @@ -11015,9 +10994,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-threads-xform" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16ddf1a4beb1bceb2b73c2325581901ca2cd92af628f24389a678854dcd65b24" +checksum = "90a2e577034352f9aa9352730fcf2562c68957f2e9b9ee70ab6379510e49e2fe" dependencies = [ "anyhow", "walrus", @@ -11026,9 +11005,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-wasm-conventions" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f13ed8ccdac31eadcfd4c9b2ec7bd43e77454b14acb1f43189f2875a9b0391" +checksum = "4e6b653f6820409609bda0f176e6949302307af7a7b9479cd4d4b1bdc31eb9cd" dependencies = [ "anyhow", "walrus", @@ -11036,9 +11015,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-wasm-interpreter" -version = "0.2.90" +version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4282a271772a3063d4057c1144e118254f207fbbc1381b8d50b23c25585d893" +checksum = "682940195a701dbf887f20017418b8cac916a37b3f91ededec33226619e973c1" dependencies = [ "anyhow", "log", @@ -11087,9 +11066,9 @@ checksum = "449167e2832691a1bff24cde28d2804e90e09586a448c8e76984792c44334a6b" [[package]] name = "web-sys" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" +checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" dependencies = [ "js-sys", "wasm-bindgen", @@ -11549,9 +11528,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.37" +version = "0.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cad8365489051ae9f054164e459304af2e7e9bb407c958076c8bf4aef52da5" +checksum = "5389a154b01683d28c77f8f68f49dea75f0a4da32557a58f68ee51ebba472d29" dependencies = [ "memchr", ] @@ -11654,11 +11633,11 @@ dependencies = [ [[package]] name = "xdg-home" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd" +checksum = "21e5a325c3cb8398ad6cf859c1135b25dd29e186679cf2da7581d9679f63b38e" dependencies = [ - "nix 0.26.4", + "libc", "winapi", ] @@ -11691,9 +11670,9 @@ dependencies = [ [[package]] name = "zbus" -version = "3.14.1" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31de390a2d872e4cd04edd71b425e29853f786dc99317ed72d73d6fcf5ebb948" +checksum = "c45d06ae3b0f9ba1fb2671268b975557d8f5a84bb5ec6e43964f87e763d8bca8" dependencies = [ "async-broadcast", "async-executor", @@ -11732,9 +11711,9 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "3.14.1" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d1794a946878c0e807f55a397187c11fc7a038ba5d868e7db4f3bd7760bc9d" +checksum = "b4a1ba45ed0ad344b85a2bb5a1fe9830aed23d67812ea39a586e7d0136439c7d" dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 9404619a2..ecda69329 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -127,7 +127,7 @@ reqwest = { version = "0.11.9", features = ["json"], optional = true} http-range = {version = "0.1.5", optional = true } [dev-dependencies] -dioxus = { workspace = true, features = ["router"]} +dioxus = { workspace = true, features = ["router"] } dioxus-ssr = { workspace = true } futures-util = "0.3.21" separator = "0.4.1" diff --git a/packages/signals/Cargo.toml b/packages/signals/Cargo.toml index e13da5dc0..d5ed4494d 100644 --- a/packages/signals/Cargo.toml +++ b/packages/signals/Cargo.toml @@ -25,8 +25,7 @@ futures-util = { workspace = true } flume = { version = "0.11.0", default-features = false, features = ["async"] } [dev-dependencies] -dioxus = { workspace = true, features = ["desktop"]} -# dioxus-desktop = { workspace = true } +dioxus = { workspace = true } tokio = { version = "1", features = ["full"] } tracing-subscriber = "0.3.17" simple_logger = "4.2.0" From b88c66d8dfdffdaf3204ff17fb4e99444793ff0a Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 8 Feb 2024 10:00:25 -0600 Subject: [PATCH 12/43] report syn parse errors to the user --- Cargo.lock | 2 ++ packages/autofmt/src/lib.rs | 7 ------ packages/cli/Cargo.toml | 4 ++++ packages/cli/src/cli/autoformat.rs | 34 ++++++++++++++++++++---------- packages/cli/src/main.rs | 1 - 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 471818cf6..3477f46ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2418,12 +2418,14 @@ dependencies = [ "mlua", "notify", "open", + "prettier-please", "rayon", "reqwest", "rsx-rosetta", "serde", "serde_json", "subprocess", + "syn 2.0.48", "tar", "tauri-bundler", "tempfile", diff --git a/packages/autofmt/src/lib.rs b/packages/autofmt/src/lib.rs index 953f052b0..e40b873d6 100644 --- a/packages/autofmt/src/lib.rs +++ b/packages/autofmt/src/lib.rs @@ -240,10 +240,3 @@ pub(crate) fn write_ifmt(input: &IfmtInput, writable: &mut impl Write) -> std::f let display = DisplayIfmt(input); write!(writable, "{}", display) } - -/// Call rustfmt to format code, i32 as exitcode -pub fn rustfmt(input: &str) -> Option { - let syntax_tree = syn::parse_file(input).ok()?; - let output = prettyplease::unparse(&syntax_tree); - Some(output) -} diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index 82c16e0dc..657c70e0f 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -75,6 +75,10 @@ toml_edit = "0.21.0" # bundling tauri-bundler = { version = "=1.4.*", features = ["native-tls-vendored"] } +# formatting +syn = { version = "2.0" } +prettyplease = { workspace = true } + manganis-cli-support = { workspace = true, features = ["webp", "html"] } dioxus-autofmt = { workspace = true } diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index 2b8093f75..36072b967 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -33,8 +33,7 @@ pub struct Autoformat { } impl Autoformat { - // Todo: autoformat the entire crate - pub async fn autoformat(self) -> Result<()> { + pub fn autoformat(self) -> Result<()> { let Autoformat { check, raw, @@ -46,7 +45,7 @@ impl Autoformat { // Default to formatting the project if raw.is_none() && file.is_none() { - if let Err(e) = autoformat_project(check, split_line_attributes, do_rustfmt).await { + if let Err(e) = autoformat_project(check, split_line_attributes, do_rustfmt) { eprintln!("error formatting project: {}", e); exit(1); } @@ -87,7 +86,7 @@ fn refactor_file(file: String, split_line_attributes: bool, do_rustfmt: bool) -> }; if do_rustfmt { - s = dioxus_autofmt::rustfmt(&s).ok_or_else(|| Error::ParseError("Syntax Error".into()))?; + s = rustfmt(&s)?; } let edits = dioxus_autofmt::fmt_file(&s, indent); @@ -122,8 +121,8 @@ fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) let mut contents = fs::read_to_string(&path)?; let mut if_write = false; if do_rustfmt { - let formatted = dioxus_autofmt::rustfmt(&contents) - .ok_or_else(|| Error::ParseError("Syntax Error".into()))?; + let formatted = rustfmt(&contents) + .map_err(|err| Error::ParseError(format!("Syntax Error:\n{}", err)))?; if contents != formatted { if_write = true; contents = formatted; @@ -150,11 +149,7 @@ fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) /// Runs using rayon for multithreading, so it should be really really fast /// /// Doesn't do mod-descending, so it will still try to format unreachable files. TODO. -async fn autoformat_project( - check: bool, - split_line_attributes: bool, - do_rustfmt: bool, -) -> Result<()> { +fn autoformat_project(check: bool, split_line_attributes: bool, do_rustfmt: bool) -> Result<()> { let files_to_format = get_project_files(); if files_to_format.is_empty() { @@ -238,6 +233,23 @@ fn indentation_for( )) } +/// Format rust code using prettyplease +pub fn rustfmt(input: &str) -> Result { + let syntax_tree = syn::parse_file(input).map_err(format_syn_error)?; + let output = prettyplease::unparse(&syntax_tree); + Ok(output) +} + +fn format_syn_error(err: syn::Error) -> Error { + let start = err.span().start(); + let line = start.line; + let column = start.column; + Error::ParseError(format!( + "Syntax Error in line {} column {}:\n{}", + line, column, err + )) +} + #[tokio::test] async fn test_auto_fmt() { let test_rsx = r#" diff --git a/packages/cli/src/main.rs b/packages/cli/src/main.rs index 0a57735db..dae2deb2c 100644 --- a/packages/cli/src/main.rs +++ b/packages/cli/src/main.rs @@ -70,7 +70,6 @@ async fn main() -> anyhow::Result<()> { Autoformat(opts) => opts .autoformat() - .await .context(error_wrapper("Error autoformatting RSX")), Check(opts) => opts From 23e15ee9c81cd47e2763090d91369d7a65ac1217 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 8 Feb 2024 10:03:52 -0600 Subject: [PATCH 13/43] change rustfmt flag to all_code now that we don't use rustfmt --- packages/cli/src/cli/autoformat.rs | 42 +++++++++++++++++++----------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index 36072b967..2855fcbe9 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -10,9 +10,9 @@ use super::*; /// Format some rsx #[derive(Clone, Debug, Parser)] pub struct Autoformat { - /// Run rustfmt before the dioxus formatter` + /// Format rust code before the formatting the rsx macros #[clap(long)] - pub rustfmt: bool, + pub all_code: bool, /// Run in 'check' mode. Exits with 0 if input is formatted correctly. Exits /// with 1 and prints a diff if formatting is required. @@ -39,13 +39,13 @@ impl Autoformat { raw, file, split_line_attributes, - rustfmt: do_rustfmt, + all_code: format_rust_code, .. } = self; // Default to formatting the project if raw.is_none() && file.is_none() { - if let Err(e) = autoformat_project(check, split_line_attributes, do_rustfmt) { + if let Err(e) = autoformat_project(check, split_line_attributes, format_rust_code) { eprintln!("error formatting project: {}", e); exit(1); } @@ -64,14 +64,18 @@ impl Autoformat { // Format single file if let Some(file) = file { - refactor_file(file, split_line_attributes, do_rustfmt)?; + refactor_file(file, split_line_attributes, format_rust_code)?; } Ok(()) } } -fn refactor_file(file: String, split_line_attributes: bool, do_rustfmt: bool) -> Result<(), Error> { +fn refactor_file( + file: String, + split_line_attributes: bool, + format_rust_code: bool, +) -> Result<(), Error> { let indent = indentation_for(".", split_line_attributes)?; let file_content = if file == "-" { let mut contents = String::new(); @@ -85,8 +89,8 @@ fn refactor_file(file: String, split_line_attributes: bool, do_rustfmt: bool) -> exit(1); }; - if do_rustfmt { - s = rustfmt(&s)?; + if format_rust_code { + s = format_rust(&s)?; } let edits = dioxus_autofmt::fmt_file(&s, indent); @@ -117,11 +121,15 @@ fn get_project_files() -> Vec { files } -fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) -> Result { +fn format_file( + path: impl AsRef, + indent: IndentOptions, + format_rust_code: bool, +) -> Result { let mut contents = fs::read_to_string(&path)?; let mut if_write = false; - if do_rustfmt { - let formatted = rustfmt(&contents) + if format_rust_code { + let formatted = format_rust(&contents) .map_err(|err| Error::ParseError(format!("Syntax Error:\n{}", err)))?; if contents != formatted { if_write = true; @@ -149,7 +157,11 @@ fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) /// Runs using rayon for multithreading, so it should be really really fast /// /// Doesn't do mod-descending, so it will still try to format unreachable files. TODO. -fn autoformat_project(check: bool, split_line_attributes: bool, do_rustfmt: bool) -> Result<()> { +fn autoformat_project( + check: bool, + split_line_attributes: bool, + format_rust_code: bool, +) -> Result<()> { let files_to_format = get_project_files(); if files_to_format.is_empty() { @@ -165,7 +177,7 @@ fn autoformat_project(check: bool, split_line_attributes: bool, do_rustfmt: bool let counts = files_to_format .into_par_iter() .map(|path| { - let res = format_file(&path, indent.clone(), do_rustfmt); + let res = format_file(&path, indent.clone(), format_rust_code); match res { Ok(cnt) => Some(cnt), Err(err) => { @@ -234,7 +246,7 @@ fn indentation_for( } /// Format rust code using prettyplease -pub fn rustfmt(input: &str) -> Result { +fn format_rust(input: &str) -> Result { let syntax_tree = syn::parse_file(input).map_err(format_syn_error)?; let output = prettyplease::unparse(&syntax_tree); Ok(output) @@ -268,7 +280,7 @@ async fn test_auto_fmt() { .to_string(); let fmt = Autoformat { - rustfmt: false, + all_code: false, check: false, raw: Some(test_rsx), file: None, From d1ed15c2ace4efba1dd86a807986de15782a0b86 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 8 Feb 2024 10:13:57 -0600 Subject: [PATCH 14/43] fix autofmt tests --- packages/cli/src/cli/autoformat.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index 2855fcbe9..b3d6cedf9 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -287,7 +287,7 @@ async fn test_auto_fmt() { split_line_attributes: false, }; - fmt.autoformat().await.unwrap(); + fmt.autoformat().unwrap(); } /*#[test] From fb2e77a68ac3b90948fc36565769e192389b3fa1 Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 16:31:46 -0500 Subject: [PATCH 15/43] feat: prerelease docs --- .github/workflows/docs.yml | 70 +++++++++++++++----------------------- 1 file changed, 28 insertions(+), 42 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 7701209c1..63893847b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,49 +1,35 @@ -name: github pages - +name: Deploy Nightly Docs on: - workflow_dispatch: - # push: - # paths: - # - docs/** - # - .github/workflows/docs.yml - # branches: - # - master - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true + push: + branches: + - master + - main jobs: - build-deploy: - runs-on: ubuntu-latest - environment: docs - steps: + deploy: Deploy + runs-on: ubuntu-latest + permissions: + contents: write - # NOTE: Comment out when https://github.com/rust-lang/mdBook/pull/1306 is merged and released - # - name: Setup mdBook - # uses: peaceiris/actions-mdbook@v1 - # with: - # mdbook-version: "0.4.10" + steps: + - name: Clone Repo + uses: actions/checkout@v4 - # NOTE: Delete when the previous one is enabled - - name: Setup mdBook - run: | - cargo install mdbook --git https://github.com/Demonthos/mdBook.git --branch master - - uses: actions/checkout@v4 + - name: Set up cargo cache + uses: Swatinem/rust-cache@v2 + with: + prefix-key: "v0-docs" - - name: Build - run: cd docs && - cd guide && mdbook build -d ../nightly/guide && cd .. && - cd router && mdbook build -d ../nightly/router && cd .. - # cd reference && mdbook build -d ../nightly/reference && cd .. && - # cd fermi && mdbook build -d ../nightly/fermi && cd .. + - name: cargo doc + run: cargo doc --no-deps --workspace - - name: Deploy 🚀 - uses: JamesIves/github-pages-deploy-action@v4.5.0 - with: - branch: gh-pages # The branch the action should deploy to. - folder: docs/nightly # The folder the action should deploy. - target-folder: docs/nightly - repository-name: dioxuslabs/docsite - clean: false - token: ${{ secrets.DEPLOY_KEY }} # let's pretend I don't need it for now + - name: upload artifacts + uses: actions/upload-pages-artifact@v3 + + - name: Deploy + uses: JamesIves/github-pages-deploy-action@v4.5.0 + with: + branch: gh-pages-docs + folder: target/doc + #target-folder: docs + #repository-name: \ No newline at end of file From 744d53147dfe0cfcc18108a0dae70c926df17d26 Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 16:33:28 -0500 Subject: [PATCH 16/43] fix: prerelease docs --- .github/workflows/docs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 63893847b..ada4f081b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -6,7 +6,8 @@ on: - main jobs: - deploy: Deploy + deploy: + name: deploy runs-on: ubuntu-latest permissions: contents: write From 0aa2917071f8513f8f3eb43c94152bf50597be93 Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 16:34:15 -0500 Subject: [PATCH 17/43] fix: prerelease docs --- .github/workflows/docs.yml | 42 +++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index ada4f081b..a128e1909 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -7,30 +7,30 @@ on: jobs: deploy: - name: deploy - runs-on: ubuntu-latest - permissions: - contents: write + name: deploy + runs-on: ubuntu-latest + permissions: + contents: write - steps: - - name: Clone Repo - uses: actions/checkout@v4 + steps: + - name: Clone Repo + uses: actions/checkout@v4 - - name: Set up cargo cache - uses: Swatinem/rust-cache@v2 - with: + - name: Set up cargo cache + uses: Swatinem/rust-cache@v2 + with: prefix-key: "v0-docs" - - name: cargo doc - run: cargo doc --no-deps --workspace + - name: cargo doc + run: cargo doc --no-deps --workspace - - name: upload artifacts - uses: actions/upload-pages-artifact@v3 + - name: upload artifacts + uses: actions/upload-pages-artifact@v3 - - name: Deploy - uses: JamesIves/github-pages-deploy-action@v4.5.0 - with: - branch: gh-pages-docs - folder: target/doc - #target-folder: docs - #repository-name: \ No newline at end of file + - name: Deploy + uses: JamesIves/github-pages-deploy-action@v4.5.0 + with: + branch: gh-pages-docs + folder: target/doc + #target-folder: docs + #repository-name: \ No newline at end of file From 28f39f0860600fc5bd21438a141062e8b586e105 Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 16:35:59 -0500 Subject: [PATCH 18/43] fix: prerelease docs --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index a128e1909..861d95d60 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -7,7 +7,7 @@ on: jobs: deploy: - name: deploy + name: Build & Deploy runs-on: ubuntu-latest permissions: contents: write From 9c1ac766632ab3102eb046f49e72048955c32197 Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 16:40:38 -0500 Subject: [PATCH 19/43] fix: prerelease docs --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 861d95d60..f6cd49670 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -19,7 +19,7 @@ jobs: - name: Set up cargo cache uses: Swatinem/rust-cache@v2 with: - prefix-key: "v0-docs" + prefix-key: 'v0-docs' - name: cargo doc run: cargo doc --no-deps --workspace From 58c27041c1f3851325fd8dbc01c36b95c2a51aeb Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 16:41:11 -0500 Subject: [PATCH 20/43] fix: prerelease docs --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index f6cd49670..48b85e5a3 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -19,7 +19,7 @@ jobs: - name: Set up cargo cache uses: Swatinem/rust-cache@v2 with: - prefix-key: 'v0-docs' + prefix-key: 'v0-docs' - name: cargo doc run: cargo doc --no-deps --workspace From 5df01eab4f7358b30bc750e252b2781ce9a35024 Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 16:50:23 -0500 Subject: [PATCH 21/43] fix: prerelease docs --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 48b85e5a3..d1e24144b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -22,7 +22,7 @@ jobs: prefix-key: 'v0-docs' - name: cargo doc - run: cargo doc --no-deps --workspace + run: cargo doc --no-deps --workspace --keep-going - name: upload artifacts uses: actions/upload-pages-artifact@v3 From 5803ac8e9e4918ac5cfa63d9a43fea3d886a461a Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 17:14:52 -0500 Subject: [PATCH 22/43] fix: prerelease docs --- .github/workflows/docs.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index d1e24144b..3583b753d 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -13,16 +13,15 @@ jobs: contents: write steps: - - name: Clone Repo - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + - run: sudo apt-get update + - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 - - name: Set up cargo cache - uses: Swatinem/rust-cache@v2 - with: - prefix-key: 'v0-docs' - name: cargo doc - run: cargo doc --no-deps --workspace --keep-going + run: cargo doc --no-deps --workspace - name: upload artifacts uses: actions/upload-pages-artifact@v3 From 1fc194c93c9cdbd0a7dd9f5fac880dc14192708b Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 17:17:06 -0500 Subject: [PATCH 23/43] fix: prerelease docs --- .github/workflows/docs.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 3583b753d..9cf357e30 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -3,7 +3,6 @@ on: push: branches: - master - - main jobs: deploy: @@ -18,6 +17,10 @@ jobs: - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 + with: + cache-all-crates: "true" + save-if: ${{ github.ref == 'refs/heads/master' }} + - uses: ilammy/setup-nasm@v1 - name: cargo doc From e9c65e3e8e4ad35c56ab2cc69cc062d1051fb0f2 Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 17:30:32 -0500 Subject: [PATCH 24/43] fix: prerelease docs --- .github/workflows/docs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 9cf357e30..76e493714 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -6,6 +6,7 @@ on: jobs: deploy: + if: github.event.pull_request.draft == false name: Build & Deploy runs-on: ubuntu-latest permissions: @@ -24,7 +25,7 @@ jobs: - name: cargo doc - run: cargo doc --no-deps --workspace + run: cargo doc --no-deps --workspace --features fullstack/server - name: upload artifacts uses: actions/upload-pages-artifact@v3 From eea70dc1f2be6abd88067a4ec347a87e2aa9a32b Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 17:31:10 -0500 Subject: [PATCH 25/43] fix: prerelease docs --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 76e493714..10f1b948f 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -6,7 +6,7 @@ on: jobs: deploy: - if: github.event.pull_request.draft == false + if: github.event.pull_request.draft == false name: Build & Deploy runs-on: ubuntu-latest permissions: From 2d723c0e28e610d18feb866e9f81a00019d6d1c7 Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 17:34:21 -0500 Subject: [PATCH 26/43] fix: prerelease docs --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 10f1b948f..6583203cd 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -25,7 +25,7 @@ jobs: - name: cargo doc - run: cargo doc --no-deps --workspace --features fullstack/server + run: cargo doc --no-deps --workspace --features "fullstack/server" - name: upload artifacts uses: actions/upload-pages-artifact@v3 From bdeea13a2d26758eb3b56cddb2605be894391d60 Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 17:36:05 -0500 Subject: [PATCH 27/43] fix: prerelease docs --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6583203cd..0b16cf3f7 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -25,7 +25,7 @@ jobs: - name: cargo doc - run: cargo doc --no-deps --workspace --features "fullstack/server" + run: cargo doc --no-deps --workspace --features server - name: upload artifacts uses: actions/upload-pages-artifact@v3 From 43c4bc46b7a02ad2fb88f83685eec0d48dd74621 Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 17:43:07 -0500 Subject: [PATCH 28/43] fix: prerelease docs --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 0b16cf3f7..5818d5fc9 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -25,7 +25,7 @@ jobs: - name: cargo doc - run: cargo doc --no-deps --workspace --features server + run: cargo doc --no-deps --workspace --features doc - name: upload artifacts uses: actions/upload-pages-artifact@v3 From b43ae755ce5e9b2cdf0383bdaee32b0cd1bd5911 Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 17:46:19 -0500 Subject: [PATCH 29/43] fix: prerelease docs --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 5818d5fc9..7ce54927e 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -25,7 +25,7 @@ jobs: - name: cargo doc - run: cargo doc --no-deps --workspace --features doc + run: cargo doc --no-deps --workspace --exclude fullstack - name: upload artifacts uses: actions/upload-pages-artifact@v3 From 3c1028c52361bad64cfb258071f9b26a4e6801b6 Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 17:53:45 -0500 Subject: [PATCH 30/43] fix: prerelease doc --- .github/workflows/docs.yml | 2 +- packages/fullstack/Cargo.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 7ce54927e..f94265837 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -25,7 +25,7 @@ jobs: - name: cargo doc - run: cargo doc --no-deps --workspace --exclude fullstack + run: cargo doc --no-deps --workspace --features dioxus-fullstack/doc - name: upload artifacts uses: actions/upload-pages-artifact@v3 diff --git a/packages/fullstack/Cargo.toml b/packages/fullstack/Cargo.toml index 8e77e84fe..c9a57c8f8 100644 --- a/packages/fullstack/Cargo.toml +++ b/packages/fullstack/Cargo.toml @@ -81,3 +81,4 @@ salvo = ["dep:salvo", "server", "http-body-util"] server = ["server_fn/ssr", "dioxus_server_macro/server", "tokio", "tokio-util", "tokio-stream", "dioxus-ssr", "dioxus-ssr/incremental", "tower", "hyper", "http", "tower-layer", "anymap", "tracing-futures", "pin-project", "thiserror", "dioxus-cli-config"] default-tls = ["server_fn/default-tls"] rustls = ["server_fn/rustls"] +doc = ["thiserror"] From 374ff24141935bd4aced88a25a7344c986d6aadb Mon Sep 17 00:00:00 2001 From: Miles Murgaw Date: Thu, 8 Feb 2024 18:02:14 -0500 Subject: [PATCH 31/43] fix: prerelease docs --- .github/workflows/docs.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index f94265837..61c4140df 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -27,9 +27,6 @@ jobs: - name: cargo doc run: cargo doc --no-deps --workspace --features dioxus-fullstack/doc - - name: upload artifacts - uses: actions/upload-pages-artifact@v3 - - name: Deploy uses: JamesIves/github-pages-deploy-action@v4.5.0 with: From 6ca877eb6d569e52fcbdd0eb4d4feee8e9e602ca Mon Sep 17 00:00:00 2001 From: Anatol Ulrich <45840+spookyvision@users.noreply.github.com> Date: Fri, 9 Feb 2024 12:02:32 +0100 Subject: [PATCH 32/43] fix `HasFileData` for `WebDragData` --- packages/web/src/event.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/web/src/event.rs b/packages/web/src/event.rs index e79b55fe8..b6aa63077 100644 --- a/packages/web/src/event.rs +++ b/packages/web/src/event.rs @@ -10,7 +10,7 @@ use dioxus_html::{ }; use js_sys::Array; use wasm_bindgen::{prelude::wasm_bindgen, JsCast, JsValue}; -use web_sys::{Document, Element, Event, MouseEvent}; +use web_sys::{Document, DragEvent, Element, Event, MouseEvent}; pub(crate) struct WebEventConverter; @@ -529,17 +529,16 @@ impl HasFileData for WebDragData { #[cfg(not(feature = "file_engine"))] let files = None; #[cfg(feature = "file_engine")] - let files = self - .element - .dyn_ref() - .and_then(|input: &web_sys::HtmlInputElement| { - input.files().and_then(|files| { + let files = self.raw.dyn_ref::().and_then(|drag_event| { + drag_event.data_transfer().and_then(|dt| { + dt.files().and_then(|files| { #[allow(clippy::arc_with_non_send_sync)] crate::file_engine::WebFileEngine::new(files).map(|f| { std::sync::Arc::new(f) as std::sync::Arc }) }) - }); + }) + }); files } From b4d17abfc1cd7f4010ee5ccd81becd8bbec940f0 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 9 Feb 2024 12:15:59 -0600 Subject: [PATCH 33/43] document all features --- .github/workflows/docs.yml | 8 +- packages/cli/src/server/mod.rs | 6 - packages/fullstack/Cargo.toml | 3 +- .../examples/axum-desktop/src/client.rs | 4 +- .../examples/axum-desktop/src/server.rs | 2 +- .../examples/static-hydrated/src/main.rs | 2 +- .../fullstack/src/adapters/axum_adapter.rs | 6 +- packages/fullstack/src/adapters/mod.rs | 4 +- .../fullstack/src/adapters/salvo_adapter.rs | 19 +- .../fullstack/src/adapters/warp_adapter.rs | 10 +- packages/fullstack/src/config.rs | 8 + packages/fullstack/src/lib.rs | 62 ++++++- packages/fullstack/src/server_context.rs | 1 + packages/fullstack/src/server_fn.rs | 22 ++- packages/hooks/src/lib.rs | 1 - packages/liveview/src/launch.rs | 4 +- packages/router/Cargo.toml | 1 - packages/router/src/components/router.rs | 78 -------- packages/router/src/history/web.rs | 168 ------------------ packages/router/src/history/web_history.rs | 42 ----- packages/router/src/router_cfg.rs | 33 ---- 21 files changed, 110 insertions(+), 374 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 61c4140df..7a365dceb 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -6,7 +6,6 @@ on: jobs: deploy: - if: github.event.pull_request.draft == false name: Build & Deploy runs-on: ubuntu-latest permissions: @@ -16,21 +15,18 @@ jobs: - uses: actions/checkout@v4 - run: sudo apt-get update - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@nightly - uses: Swatinem/rust-cache@v2 with: cache-all-crates: "true" save-if: ${{ github.ref == 'refs/heads/master' }} - uses: ilammy/setup-nasm@v1 - - name: cargo doc - run: cargo doc --no-deps --workspace --features dioxus-fullstack/doc + run: cargo doc --no-deps --workspace --all-features - name: Deploy uses: JamesIves/github-pages-deploy-action@v4.5.0 with: branch: gh-pages-docs folder: target/doc - #target-folder: docs - #repository-name: \ No newline at end of file diff --git a/packages/cli/src/server/mod.rs b/packages/cli/src/server/mod.rs index bd1cafdd8..3f9510839 100644 --- a/packages/cli/src/server/mod.rs +++ b/packages/cli/src/server/mod.rs @@ -112,12 +112,6 @@ async fn setup_file_watcher Result + Send + 'static>( }, web_info.clone(), ); - - #[cfg(feature = "plugin")] - let _ = PluginManager::on_serve_rebuild( - chrono::Local::now().timestamp(), - e.paths, - ); } Err(e) => { last_update_time = chrono::Local::now().timestamp(); diff --git a/packages/fullstack/Cargo.toml b/packages/fullstack/Cargo.toml index c9a57c8f8..63fde221c 100644 --- a/packages/fullstack/Cargo.toml +++ b/packages/fullstack/Cargo.toml @@ -81,4 +81,5 @@ salvo = ["dep:salvo", "server", "http-body-util"] server = ["server_fn/ssr", "dioxus_server_macro/server", "tokio", "tokio-util", "tokio-stream", "dioxus-ssr", "dioxus-ssr/incremental", "tower", "hyper", "http", "tower-layer", "anymap", "tracing-futures", "pin-project", "thiserror", "dioxus-cli-config"] default-tls = ["server_fn/default-tls"] rustls = ["server_fn/rustls"] -doc = ["thiserror"] +# This feature enables some nightly flags that make it more clear what structs/methods are available in each feature +nightly-doc = [] diff --git a/packages/fullstack/examples/axum-desktop/src/client.rs b/packages/fullstack/examples/axum-desktop/src/client.rs index da11fda25..247f2e8f2 100644 --- a/packages/fullstack/examples/axum-desktop/src/client.rs +++ b/packages/fullstack/examples/axum-desktop/src/client.rs @@ -4,10 +4,10 @@ // ``` use axum_desktop::*; -use dioxus_fullstack::prelude::server_fn::set_server_url; fn main() { // Set the url of the server where server functions are hosted. - set_server_url("http://127.0.0.1:8080"); + #[cfg(not(feature = "server"))] + dioxus::fullstack::prelude::server_fn::set_server_url("http://127.0.0.1:8080"); dioxus::desktop::launch(app) } diff --git a/packages/fullstack/examples/axum-desktop/src/server.rs b/packages/fullstack/examples/axum-desktop/src/server.rs index 0781db5fb..759d5799b 100644 --- a/packages/fullstack/examples/axum-desktop/src/server.rs +++ b/packages/fullstack/examples/axum-desktop/src/server.rs @@ -4,7 +4,7 @@ // ``` use axum_desktop::*; -use dioxus_fullstack::prelude::*; +use dioxus::prelude::*; #[tokio::main] async fn main() { diff --git a/packages/fullstack/examples/static-hydrated/src/main.rs b/packages/fullstack/examples/static-hydrated/src/main.rs index 72bd6894b..69c81b40e 100644 --- a/packages/fullstack/examples/static-hydrated/src/main.rs +++ b/packages/fullstack/examples/static-hydrated/src/main.rs @@ -27,7 +27,7 @@ async fn main() { } // Hydrate the page -#[cfg(feature = "web")] +#[cfg(all(feature = "web", not(feature = "server")))] fn main() { dioxus_web::launch_with_props( dioxus_fullstack::router::RouteWithCfg::, diff --git a/packages/fullstack/src/adapters/axum_adapter.rs b/packages/fullstack/src/adapters/axum_adapter.rs index 731b3f13e..d73edeb88 100644 --- a/packages/fullstack/src/adapters/axum_adapter.rs +++ b/packages/fullstack/src/adapters/axum_adapter.rs @@ -332,7 +332,7 @@ where } fn connect_hot_reload(self) -> Self { - #[cfg(all(debug_assertions, feature = "hot-reload", feature = "server"))] + #[cfg(all(debug_assertions, feature = "hot-reload"))] { self.nest( "/_dioxus", @@ -354,7 +354,7 @@ where .route("/hot_reload", get(hot_reload_handler)), ) } - #[cfg(not(all(debug_assertions, feature = "hot-reload", feature = "server")))] + #[cfg(not(all(debug_assertions, feature = "hot-reload")))] { self } @@ -476,7 +476,7 @@ fn report_err(e: E) -> Response { } /// A handler for Dioxus web hot reload websocket. This will send the updated static parts of the RSX to the client when they change. -#[cfg(all(debug_assertions, feature = "hot-reload", feature = "server"))] +#[cfg(all(debug_assertions, feature = "hot-reload"))] pub async fn hot_reload_handler(ws: axum::extract::WebSocketUpgrade) -> impl IntoResponse { use axum::extract::ws::Message; use futures_util::StreamExt; diff --git a/packages/fullstack/src/adapters/mod.rs b/packages/fullstack/src/adapters/mod.rs index d368b9c73..61f24bf3c 100644 --- a/packages/fullstack/src/adapters/mod.rs +++ b/packages/fullstack/src/adapters/mod.rs @@ -12,8 +12,8 @@ #[cfg(feature = "axum")] pub mod axum_adapter; -#[cfg(feature = "salvo")] -pub mod salvo_adapter; +// #[cfg(feature = "salvo")] +// pub mod salvo_adapter; #[cfg(feature = "warp")] pub mod warp_adapter; diff --git a/packages/fullstack/src/adapters/salvo_adapter.rs b/packages/fullstack/src/adapters/salvo_adapter.rs index 4c41fc4a4..a30097c9a 100644 --- a/packages/fullstack/src/adapters/salvo_adapter.rs +++ b/packages/fullstack/src/adapters/salvo_adapter.rs @@ -291,17 +291,20 @@ impl DioxusRouterExt for Router { ) -> Self { let cfg = cfg.into(); - self.serve_static_assets(cfg.assets_path) + self.serve_static_assets(cfg.assets_path.clone()) .connect_hot_reload() .register_server_fns(server_fn_path) - .push(Router::with_path("/<**any_path>").get(SSRHandler { cfg })) + .push(Router::with_path("/<**any_path>").get(SSRHandler { + config: cfg, + virtual_dom: virtual_dom_factory, + })) } fn connect_hot_reload(self) -> Self { let mut _dioxus_router = Router::with_path("_dioxus"); _dioxus_router = _dioxus_router.push(Router::with_path("hot_reload").handle(HotReloadHandler)); - #[cfg(all(debug_assertions, feature = "hot-reload", feature = "server"))] + #[cfg(all(debug_assertions, feature = "hot-reload"))] { _dioxus_router = _dioxus_router.push(Router::with_path("disconnect").handle(ignore_ws)); } @@ -485,11 +488,11 @@ fn handle_error(error: impl Error + Send + Sync, res: &mut Response) { } /// A handler for Dioxus web hot reload websocket. This will send the updated static parts of the RSX to the client when they change. -#[cfg(not(all(debug_assertions, feature = "hot-reload", feature = "server")))] +#[cfg(not(all(debug_assertions, feature = "hot-reload")))] #[derive(Default)] pub struct HotReloadHandler; -#[cfg(not(all(debug_assertions, feature = "hot-reload", feature = "server")))] +#[cfg(not(all(debug_assertions, feature = "hot-reload")))] #[handler] impl HotReloadHandler { async fn handle( @@ -503,11 +506,11 @@ impl HotReloadHandler { } /// A handler for Dioxus web hot reload websocket. This will send the updated static parts of the RSX to the client when they change. -#[cfg(all(debug_assertions, feature = "hot-reload", feature = "server"))] +#[cfg(all(debug_assertions, feature = "hot-reload"))] #[derive(Default)] pub struct HotReloadHandler; -#[cfg(all(debug_assertions, feature = "hot-reload", feature = "server"))] +#[cfg(all(debug_assertions, feature = "hot-reload"))] #[handler] impl HotReloadHandler { async fn handle( @@ -561,7 +564,7 @@ impl HotReloadHandler { } } -#[cfg(all(debug_assertions, feature = "hot-reload", feature = "server"))] +#[cfg(all(debug_assertions, feature = "hot-reload"))] #[handler] async fn ignore_ws(req: &mut Request, res: &mut Response) -> Result<(), salvo::http::StatusError> { use salvo::websocket::WebSocketUpgrade; diff --git a/packages/fullstack/src/adapters/warp_adapter.rs b/packages/fullstack/src/adapters/warp_adapter.rs index 462fce1f6..711980ec8 100644 --- a/packages/fullstack/src/adapters/warp_adapter.rs +++ b/packages/fullstack/src/adapters/warp_adapter.rs @@ -187,7 +187,7 @@ pub fn serve_dioxus_application( ) -> BoxedFilter<(impl Reply,)> { let cfg = cfg.into(); // Serve the dist folder and the index.html file - let serve_dir = warp::fs::dir(cfg.assets_path); + let serve_dir = warp::fs::dir(cfg.assets_path.clone()); let virtual_dom_factory = Arc::new(virtual_dom_factory) as Arc VirtualDom + Send + Sync + 'static>; @@ -332,13 +332,13 @@ impl warp::reject::Reject for RecieveFailed {} /// ``` pub fn connect_hot_reload() -> impl Filter + Clone { - #[cfg(not(all(debug_assertions, feature = "hot-reload", feature = "server")))] + #[cfg(not(all(debug_assertions, feature = "hot-reload")))] { warp::path!("_dioxus" / "hot_reload") .map(warp::reply) .map(|reply| warp::reply::with_status(reply, warp::http::StatusCode::NOT_FOUND)) } - #[cfg(all(debug_assertions, feature = "hot-reload", feature = "server"))] + #[cfg(all(debug_assertions, feature = "hot-reload"))] { use crate::hot_reload::HotReloadState; use futures_util::sink::SinkExt; @@ -349,7 +349,7 @@ pub fn connect_hot_reload() -> impl Filter impl Filter); impl Drop for DisconnectOnDrop { diff --git a/packages/fullstack/src/config.rs b/packages/fullstack/src/config.rs index 765108e5f..f4416b8df 100644 --- a/packages/fullstack/src/config.rs +++ b/packages/fullstack/src/config.rs @@ -53,6 +53,7 @@ impl Config { /// Set the address to serve the app on. #[cfg(feature = "server")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] pub fn addr(self, addr: impl Into) -> Self { let addr = addr.into(); Self { addr, ..self } @@ -60,6 +61,7 @@ impl Config { /// Set the route to the server functions. #[cfg(feature = "server")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] pub fn server_fn_route(self, server_fn_route: &'static str) -> Self { Self { server_fn_route, @@ -69,6 +71,7 @@ impl Config { /// Set the incremental renderer config. #[cfg(feature = "server")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] pub fn incremental(self, cfg: IncrementalRendererConfig) -> Self { Self { server_cfg: self.server_cfg.incremental(cfg), @@ -78,18 +81,21 @@ impl Config { /// Set the server config. #[cfg(feature = "server")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] pub fn server_cfg(self, server_cfg: ServeConfigBuilder) -> Self { Self { server_cfg, ..self } } /// Set the web config. #[cfg(feature = "web")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "web")))] pub fn web_cfg(self, web_cfg: dioxus_web::Config) -> Self { Self { web_cfg, ..self } } /// Set the desktop config. #[cfg(feature = "desktop")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "desktop")))] pub fn desktop_cfg(self, desktop_cfg: dioxus_desktop::Config) -> Self { Self { desktop_cfg, @@ -99,11 +105,13 @@ impl Config { /// Set the mobile config. #[cfg(feature = "mobile")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "mobile")))] pub fn mobile_cfg(self, mobile_cfg: dioxus_mobile::Config) -> Self { Self { mobile_cfg, ..self } } #[cfg(feature = "server")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] /// Launch a server application pub async fn launch_server( self, diff --git a/packages/fullstack/src/lib.rs b/packages/fullstack/src/lib.rs index b04a3cbc9..270cbc801 100644 --- a/packages/fullstack/src/lib.rs +++ b/packages/fullstack/src/lib.rs @@ -2,6 +2,7 @@ #![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")] #![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")] #![deny(missing_docs)] +#![cfg_attr(any(docsrs, feature = "nightly-doc"), feature(doc_cfg))] pub use once_cell; @@ -9,8 +10,20 @@ mod html_storage; #[cfg(feature = "server")] mod adapters; +// Splitting up the glob export lets us document features required for each adapter +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "axum")))] +#[cfg(feature = "axum")] +pub use adapters::axum_adapter; +// TODO: Compilation seems to be broken with the salvo feature enabled. Fix and add more features to checks in CI +// #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "salvo")))] +// #[cfg(feature = "salvo")] +// pub use adapters::salvo_adapter; +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "warp")))] +#[cfg(feature = "warp")] +pub use adapters::warp_adapter; +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] #[cfg(feature = "server")] -pub use adapters::*; +pub use adapters::{server_fn_service, ServerFnHandler}; mod config; mod hooks; #[cfg(all(debug_assertions, feature = "hot-reload", feature = "server"))] @@ -30,35 +43,57 @@ mod server_fn; /// A prelude of commonly used items in dioxus-fullstack. pub mod prelude { #[cfg(feature = "axum")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "axum")))] pub use crate::adapters::axum_adapter::*; - #[cfg(feature = "salvo")] - pub use crate::adapters::salvo_adapter::*; + // #[cfg(feature = "salvo")] + // #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "salvo")))] + // pub use crate::adapters::salvo_adapter::*; #[cfg(feature = "warp")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "warp")))] pub use crate::adapters::warp_adapter::*; use crate::hooks; #[cfg(not(feature = "server"))] + #[cfg_attr( + any(docsrs, feature = "nightly-doc"), + doc(cfg(not(feature = "server"))) + )] pub use crate::html_storage::deserialize::get_root_props_from_document; #[cfg(feature = "server")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] pub use crate::layer::{Layer, Service}; #[cfg(all(feature = "server", feature = "router"))] + #[cfg_attr( + any(docsrs, feature = "nightly-doc"), + doc(cfg(all(feature = "server", feature = "router"))) + )] pub use crate::render::pre_cache_static_routes_with_props; #[cfg(feature = "server")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] pub use crate::render::SSRState; #[cfg(feature = "router")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "router")))] pub use crate::router::FullstackRouterConfig; #[cfg(feature = "server")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] pub use crate::serve_config::{ServeConfig, ServeConfigBuilder}; #[cfg(all(feature = "server", feature = "axum"))] + #[cfg_attr( + any(docsrs, feature = "nightly-doc"), + doc(cfg(all(feature = "server", feature = "axum"))) + )] pub use crate::server_context::Axum; #[cfg(feature = "server")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] pub use crate::server_context::{ extract, server_context, DioxusServerContext, FromServerContext, ProvideServerContext, }; pub use crate::server_fn::DioxusServerFn; #[cfg(feature = "server")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] pub use crate::server_fn::{ServerFnMiddleware, ServerFnTraitObj, ServerFunction}; pub use dioxus_server_macro::*; #[cfg(feature = "server")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] pub use dioxus_ssr::incremental::IncrementalRendererConfig; pub use server_fn::{self, ServerFn as _, ServerFnError}; @@ -66,11 +101,26 @@ pub mod prelude { } // Warn users about overlapping features -#[cfg(all(feature = "server", feature = "web", not(doc)))] +#[cfg(all( + feature = "server", + feature = "web", + not(doc), + not(feature = "nightly-doc") +))] compile_error!("The `ssr` feature (enabled by `warp`, `axum`, or `salvo`) and `web` feature are overlapping. Please choose one or the other."); -#[cfg(all(feature = "server", feature = "desktop", not(doc)))] +#[cfg(all( + feature = "server", + feature = "desktop", + not(doc), + not(feature = "nightly-doc") +))] compile_error!("The `ssr` feature (enabled by `warp`, `axum`, or `salvo`) and `desktop` feature are overlapping. Please choose one or the other."); -#[cfg(all(feature = "server", feature = "mobile", not(doc)))] +#[cfg(all( + feature = "server", + feature = "mobile", + not(doc), + not(feature = "nightly-doc") +))] compile_error!("The `ssr` feature (enabled by `warp`, `axum`, or `salvo`) and `mobile` feature are overlapping. Please choose one or the other."); diff --git a/packages/fullstack/src/server_context.rs b/packages/fullstack/src/server_context.rs index 6f3b4b6c9..8d5966a7c 100644 --- a/packages/fullstack/src/server_context.rs +++ b/packages/fullstack/src/server_context.rs @@ -228,6 +228,7 @@ impl FromServerContext for FromContext { } #[cfg(feature = "axum")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "axum")))] /// An adapter for axum extractors for the server context pub struct Axum; diff --git a/packages/fullstack/src/server_fn.rs b/packages/fullstack/src/server_fn.rs index e71994b92..d51e4beec 100644 --- a/packages/fullstack/src/server_fn.rs +++ b/packages/fullstack/src/server_fn.rs @@ -1,9 +1,10 @@ -#[cfg(any(feature = "server", doc))] +#[cfg(feature = "server")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] #[derive(Clone)] /// A trait object for a function that be called on serializable arguments and returns a serializable result. pub struct ServerFnTraitObj(server_fn::ServerFnTraitObj<()>); -#[cfg(any(feature = "server", doc))] +#[cfg(feature = "server")] impl std::ops::Deref for ServerFnTraitObj { type Target = server_fn::ServerFnTraitObj<()>; @@ -12,14 +13,14 @@ impl std::ops::Deref for ServerFnTraitObj { } } -#[cfg(any(feature = "server", doc))] +#[cfg(feature = "server")] impl std::ops::DerefMut for ServerFnTraitObj { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } -#[cfg(any(feature = "server", doc))] +#[cfg(feature = "server")] impl ServerFnTraitObj { fn new( prefix: &'static str, @@ -40,6 +41,7 @@ impl ServerFnTraitObj { server_fn::inventory::collect!(ServerFnTraitObj); #[cfg(feature = "server")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] /// Middleware for a server function pub struct ServerFnMiddleware { /// The prefix of the server function. @@ -72,7 +74,8 @@ pub(crate) static MIDDLEWARE: once_cell::sync::Lazy< #[cfg(feature = "server")] server_fn::inventory::collect!(ServerFnMiddleware); -#[cfg(any(feature = "server", doc))] +#[cfg(feature = "server")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] /// A server function that can be called on serializable arguments and returns a serializable result. pub type ServerFunction = server_fn::SerializedFnTraitObj<()>; @@ -88,7 +91,8 @@ static REGISTERED_SERVER_FUNCTIONS: once_cell::sync::Lazy< std::sync::Arc::new(std::sync::RwLock::new(map)) }); -#[cfg(any(feature = "server", doc))] +#[cfg(feature = "server")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] /// The registry of all Dioxus server functions. pub struct DioxusServerFnRegistry; @@ -155,7 +159,8 @@ impl server_fn::ServerFunctionRegistry<()> for DioxusServerFnRegistry { } } -#[cfg(any(feature = "server", doc))] +#[cfg(feature = "server")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] /// Errors that can occur when registering a server function. #[derive(thiserror::Error, Debug, Clone, serde::Serialize, serde::Deserialize)] pub enum ServerRegistrationFnError { @@ -178,7 +183,8 @@ pub enum ServerRegistrationFnError { /// Technically, the trait is implemented on a type that describes the server function's arguments, not the function itself. pub trait DioxusServerFn: server_fn::ServerFn<()> { /// Registers the server function, allowing the client to query it by URL. - #[cfg(any(feature = "server", doc))] + #[cfg(feature = "server")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "server")))] fn register_explicit() -> Result<(), server_fn::ServerFnError> { Self::register_in_explicit::() } diff --git a/packages/hooks/src/lib.rs b/packages/hooks/src/lib.rs index 1c937ff8e..5d842b5ff 100644 --- a/packages/hooks/src/lib.rs +++ b/packages/hooks/src/lib.rs @@ -1,7 +1,6 @@ #![doc = include_str!("../README.md")] #![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")] #![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")] -#![cfg_attr(feature = "nightly-features", feature(debug_refcell))] #[macro_export] /// A helper macro for using hooks and properties in async environments. diff --git a/packages/liveview/src/launch.rs b/packages/liveview/src/launch.rs index 2b2d294a8..d008e38cd 100644 --- a/packages/liveview/src/launch.rs +++ b/packages/liveview/src/launch.rs @@ -3,9 +3,9 @@ use std::any::Any; #[cfg(feature = "axum")] pub type Config = crate::Config; -#[cfg(feature = "salvo")] +#[cfg(all(feature = "salvo", not(feature = "axum")))] pub type Config = crate::Config; -#[cfg(feature = "rocket")] +#[cfg(all(feature = "rocket", not(any(feature = "axum", feature = "salvo"))))] pub type Config = crate::Config>; /// Launches the WebView and runs the event loop, with configuration and root props. diff --git a/packages/router/Cargo.toml b/packages/router/Cargo.toml index e4f68d27f..3343f1886 100644 --- a/packages/router/Cargo.toml +++ b/packages/router/Cargo.toml @@ -35,7 +35,6 @@ default = [] ssr = ["dioxus-ssr/incremental", "tokio", "dioxus-fullstack?/server"] liveview = ["dioxus-liveview", "tokio", "dep:serde", "serde_json"] wasm_test = [] -serde = ["dep:serde", "gloo-utils?/serde"] web = ["gloo", "web-sys", "wasm-bindgen", "gloo-utils", "js-sys"] fullstack = ["dioxus-fullstack"] diff --git a/packages/router/src/components/router.rs b/packages/router/src/components/router.rs index af04fdacb..88aa349ce 100644 --- a/packages/router/src/components/router.rs +++ b/packages/router/src/components/router.rs @@ -11,18 +11,6 @@ pub struct RouterConfigFactory { config: Rc RouterConfig>>>>, } -#[cfg(feature = "serde")] -impl Default for RouterConfigFactory -where - ::Err: std::fmt::Display, - R: serde::Serialize + serde::de::DeserializeOwned, -{ - fn default() -> Self { - Self::from(RouterConfig::default) - } -} - -#[cfg(not(feature = "serde"))] impl Default for RouterConfigFactory where ::Err: std::fmt::Display, @@ -40,19 +28,6 @@ impl RouterConfig + 'static> From for RouterCo } } -#[cfg(feature = "serde")] -/// The props for [`Router`]. -#[derive(Props)] -pub struct RouterProps -where - ::Err: std::fmt::Display, - R: serde::Serialize + serde::de::DeserializeOwned, -{ - #[props(default, into)] - config: RouterConfigFactory, -} - -#[cfg(not(feature = "serde"))] /// The props for [`Router`]. #[derive(Props)] pub struct RouterProps @@ -74,7 +49,6 @@ where } } -#[cfg(not(feature = "serde"))] impl Default for RouterProps where ::Err: std::fmt::Display, @@ -86,20 +60,6 @@ where } } -#[cfg(feature = "serde")] -impl Default for RouterProps -where - ::Err: std::fmt::Display, - R: serde::Serialize + serde::de::DeserializeOwned, -{ - fn default() -> Self { - Self { - config: RouterConfigFactory::default(), - } - } -} - -#[cfg(not(feature = "serde"))] impl PartialEq for RouterProps where ::Err: std::fmt::Display, @@ -110,19 +70,6 @@ where } } -#[cfg(feature = "serde")] -impl PartialEq for RouterProps -where - ::Err: std::fmt::Display, - R: serde::Serialize + serde::de::DeserializeOwned, -{ - fn eq(&self, _: &Self) -> bool { - // prevent the router from re-rendering when the initial url or config changes - true - } -} - -#[cfg(not(feature = "serde"))] /// A component that renders the current route. pub fn Router(props: RouterProps) -> Element where @@ -148,28 +95,3 @@ where rsx! { Outlet:: {} } } - -#[cfg(feature = "serde")] -/// A component that renders the current route. -pub fn Router(cx: ScopeState>) -> Element -where - ::Err: std::fmt::Display, - R: serde::Serialize + serde::de::DeserializeOwned, -{ - use_context_provider(|| { - RouterContext::new( - (cx.props - .config - .config - .take() - .expect("use_context_provider ran twice"))(), - cx.schedule_update_any(), - ) - }); - use_context_provider(|| OutletContext:: { - current_level: 0, - _marker: std::marker::PhantomData, - }); - - rsx! { Outlet:: {} } -} diff --git a/packages/router/src/history/web.rs b/packages/router/src/history/web.rs index a0f677e24..180840d2d 100644 --- a/packages/router/src/history/web.rs +++ b/packages/router/src/history/web.rs @@ -23,7 +23,6 @@ fn base_path() -> Option<&'static str> { base_path } -#[cfg(not(feature = "serde"))] #[allow(clippy::extra_unused_type_parameters)] fn update_scroll(window: &Window, history: &History) { let scroll = ScrollPosition::of_window(window); @@ -32,27 +31,6 @@ fn update_scroll(window: &Window, history: &History) { } } -#[cfg(feature = "serde")] -fn update_scroll( - window: &Window, - history: &History, -) { - if let Some(WebHistoryState { state, .. }) = get_current::>(history) { - let scroll = ScrollPosition::of_window(window); - let state = WebHistoryState { state, scroll }; - if let Err(err) = replace_state_with_url(history, &state, None) { - error!(err); - } - } -} - -#[cfg(feature = "serde")] -#[derive(serde::Deserialize, serde::Serialize)] -struct WebHistoryState { - state: R, - scroll: ScrollPosition, -} - /// A [`HistoryProvider`] that integrates with a browser via the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API). /// /// # Prefix @@ -75,7 +53,6 @@ pub struct WebHistory { phantom: std::marker::PhantomData, } -#[cfg(not(feature = "serde"))] impl Default for WebHistory where ::Err: std::fmt::Display, @@ -85,19 +62,7 @@ where } } -#[cfg(feature = "serde")] -impl Default for WebHistory -where - ::Err: std::fmt::Display, - R: serde::Serialize + serde::de::DeserializeOwned, -{ - fn default() -> Self { - Self::new(None, true) - } -} - impl WebHistory { - #[cfg(not(feature = "serde"))] /// Create a new [`WebHistory`]. /// /// If `do_scroll_restoration` is [`true`], [`WebHistory`] will take control of the history @@ -116,47 +81,6 @@ impl WebHistory { myself } - #[cfg(feature = "serde")] - /// Create a new [`WebHistory`]. - /// - /// If `do_scroll_restoration` is [`true`], [`WebHistory`] will take control of the history - /// state. It'll also set the browsers scroll restoration to `manual`. - pub fn new(prefix: Option, do_scroll_restoration: bool) -> Self - where - ::Err: std::fmt::Display, - R: serde::Serialize + serde::de::DeserializeOwned, - { - let w = window().expect("access to `window`"); - let h = w.history().expect("`window` has access to `history`"); - let document = w.document().expect("`window` has access to `document`"); - - let myself = Self::new_inner( - prefix, - do_scroll_restoration, - EventListener::new(&document, "scroll", { - let mut last_updated = 0.0; - move |evt| { - // the time stamp in milliseconds - let time_stamp = evt.time_stamp(); - // throttle the scroll event to 100ms - if (time_stamp - last_updated) < 100.0 { - return; - } - update_scroll::(&w, &h); - last_updated = time_stamp; - } - }), - ); - - let current_route = myself.current_route(); - tracing::trace!("initial route: {:?}", current_route); - let current_url = current_route.to_string(); - let state = myself.create_state(current_route); - let _ = replace_state_with_url(&myself.history, &state, Some(¤t_url)); - - myself - } - fn new_inner(prefix: Option, do_scroll_restoration: bool) -> Self where ::Err: std::fmt::Display, @@ -191,17 +115,10 @@ impl WebHistory { .unwrap_or_default() } - #[cfg(not(feature = "serde"))] fn create_state(&self, _state: R) -> [f64; 2] { let scroll = self.scroll_pos(); [scroll.x, scroll.y] } - - #[cfg(feature = "serde")] - fn create_state(&self, state: R) -> WebHistoryState { - let scroll = self.scroll_pos(); - WebHistoryState { state, scroll } - } } impl WebHistory @@ -254,91 +171,6 @@ where } } -#[cfg(feature = "serde")] -impl HistoryProvider - for WebHistory -where - ::Err: std::fmt::Display, -{ - fn current_route(&self) -> R { - match get_current::>(&self.history) { - // Try to get the route from the history state - Some(route) => route.state, - // If that fails, get the route from the current URL - None => self.route_from_location(), - } - } - - fn current_prefix(&self) -> Option { - self.prefix.clone() - } - - fn go_back(&mut self) { - if let Err(e) = self.history.back() { - error!("failed to go back: ", e) - } - } - - fn go_forward(&mut self) { - if let Err(e) = self.history.forward() { - error!("failed to go forward: ", e) - } - } - - fn push(&mut self, state: R) { - use gloo_utils::format::JsValueSerdeExt; - if JsValue::from_serde(&state) != JsValue::from_serde(&self.current_route()) { - // don't push the same state twice - return; - } - - let w = window().expect("access to `window`"); - let h = w.history().expect("`window` has access to `history`"); - - // update the scroll position before pushing the new state - update_scroll::(&w, &h); - - let path = self.full_path(&state); - - let state = self.create_state(state); - - self.handle_nav(push_state_and_url(&self.history, &state, path)); - } - - fn replace(&mut self, state: R) { - let path = match &self.prefix { - None => format!("{state}"), - Some(prefix) => format!("{prefix}{state}"), - }; - - let state = self.create_state(state); - - self.handle_nav(replace_state_with_url(&self.history, &state, Some(&path))); - } - - fn external(&mut self, url: String) -> bool { - self.navigate_external(url) - } - - fn updater(&mut self, callback: std::sync::Arc) { - let w = self.window.clone(); - let h = self.history.clone(); - let s = self.listener_animation_frame.clone(); - let d = self.do_scroll_restoration; - - self.listener_navigation = Some(EventListener::new(&self.window, "popstate", move |_| { - (*callback)(); - if d { - let mut s = s.lock().expect("unpoisoned scroll mutex"); - if let Some(current_state) = get_current::>(&h) { - *s = Some(current_state.scroll.scroll_to(w.clone())); - } - } - })); - } -} - -#[cfg(not(feature = "serde"))] impl HistoryProvider for WebHistory where ::Err: std::fmt::Display, diff --git a/packages/router/src/history/web_history.rs b/packages/router/src/history/web_history.rs index 25a7063b4..df5219874 100644 --- a/packages/router/src/history/web_history.rs +++ b/packages/router/src/history/web_history.rs @@ -1,10 +1,7 @@ use gloo::console::error; -#[cfg(feature = "serde")] -use gloo_utils::format::JsValueSerdeExt; use wasm_bindgen::JsValue; use web_sys::History; -#[cfg(not(feature = "serde"))] pub(crate) fn replace_state_with_url( history: &History, value: &[f64; 2], @@ -17,18 +14,6 @@ pub(crate) fn replace_state_with_url( history.replace_state_with_url(&position, "", url) } -#[cfg(feature = "serde")] -pub(crate) fn replace_state_with_url( - history: &History, - value: &V, - url: Option<&str>, -) -> Result<(), JsValue> { - let position = JsValue::from_serde(value).unwrap(); - - history.replace_state_with_url(&position, "", url) -} - -#[cfg(not(feature = "serde"))] pub(crate) fn push_state_and_url( history: &History, value: &[f64; 2], @@ -41,33 +26,6 @@ pub(crate) fn push_state_and_url( history.push_state_with_url(&position, "", Some(&url)) } -#[cfg(feature = "serde")] -pub(crate) fn push_state_and_url( - history: &History, - value: &V, - url: String, -) -> Result<(), JsValue> { - let position = JsValue::from_serde(value).unwrap(); - - history.push_state_with_url(&position, "", Some(&url)) -} - -#[cfg(feature = "serde")] -pub(crate) fn get_current(history: &History) -> Option { - let state = history.state(); - if let Err(err) = &state { - error!(err); - } - state.ok().and_then(|state| { - let deserialized = state.into_serde(); - if let Err(err) = &deserialized { - error!(format!("{}", err)); - } - deserialized.ok() - }) -} - -#[cfg(not(feature = "serde"))] pub(crate) fn get_current(history: &History) -> Option<[f64; 2]> { use wasm_bindgen::JsCast; diff --git a/packages/router/src/router_cfg.rs b/packages/router/src/router_cfg.rs index 0c81faae1..30dcac10f 100644 --- a/packages/router/src/router_cfg.rs +++ b/packages/router/src/router_cfg.rs @@ -31,21 +31,6 @@ pub struct RouterConfig { pub(crate) initial_route: Option, } -#[cfg(feature = "serde")] -impl Default for RouterConfig -where - ::Err: std::fmt::Display, - R: serde::Serialize + serde::de::DeserializeOwned, -{ - fn default() -> Self { - Self { - failure_external_navigation: FailureExternalNavigation::, - history: None, - on_update: None, - } - } -} - macro_rules! default_history { ($initial_route:ident) => { { @@ -83,24 +68,6 @@ macro_rules! default_history { }; } -#[cfg(feature = "serde")] -impl RouterConfig -where - ::Err: std::fmt::Display, - R: serde::Serialize + serde::de::DeserializeOwned, -{ - pub(crate) fn get_history(self) -> Box> { - #[allow(unused)] - let initial_route = self.initial_route.clone().unwrap_or("/".parse().unwrap_or_else(|err| - panic!("index route does not exist:\n{}\n use MemoryHistory::with_initial_path or RouterConfig::initial_route to set a custom path", err) - )); - self.history - .take() - .unwrap_or_else(|| default_history!(initial_route)) - } -} - -#[cfg(not(feature = "serde"))] impl Default for RouterConfig where ::Err: std::fmt::Display, From 162b033c36e2ff1bf5ca5227e9b8403503516a3a Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 9 Feb 2024 12:23:57 -0600 Subject: [PATCH 34/43] provide feature hints for the dioxus crate as well --- packages/core/src/error_boundary.rs | 8 ++++---- packages/core/src/events.rs | 2 +- packages/core/src/lib.rs | 4 ++-- packages/core/src/virtual_dom.rs | 6 +++--- packages/dioxus/Cargo.toml | 3 +++ packages/dioxus/README.md | 23 +++++++++++------------ packages/dioxus/src/launch.rs | 9 +++++++++ packages/dioxus/src/lib.rs | 26 ++++++++++++++++++++++++++ 8 files changed, 59 insertions(+), 22 deletions(-) diff --git a/packages/core/src/error_boundary.rs b/packages/core/src/error_boundary.rs index 7fa1d2591..6e1055c6e 100644 --- a/packages/core/src/error_boundary.rs +++ b/packages/core/src/error_boundary.rs @@ -140,12 +140,12 @@ impl ErrorBoundary { /// /// ```rust, ignore /// #[component] -/// fn app( count: String) -> Element { +/// fn app(count: String) -> Element { /// let id: i32 = count.parse().throw()?; /// /// rsx! { /// div { "Count {}" } -/// }) +/// } /// } /// ``` pub trait Throw: Sized { @@ -170,7 +170,7 @@ pub trait Throw: Sized { /// /// rsx! { /// div { "Count {}" } - /// }) + /// } /// } /// ``` fn throw(self) -> Option; @@ -193,7 +193,7 @@ pub trait Throw: Sized { /// /// rsx! { /// div { "Count {}" } - /// }) + /// } /// } /// ``` fn throw_with(self, e: impl FnOnce() -> D) -> Option { diff --git a/packages/core/src/events.rs b/packages/core/src/events.rs index 2c0c92d14..7581d0bb6 100644 --- a/packages/core/src/events.rs +++ b/packages/core/src/events.rs @@ -159,7 +159,7 @@ impl std::fmt::Debug for Event { /// button { /// onclick: move |evt| cx.onclick.call(evt), /// } -/// }) +/// } /// } /// /// ``` diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index a55ce4be7..afa80eb84 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -42,7 +42,7 @@ pub(crate) mod innerlude { /// An Errored [`Element`] will propagate the error to the nearest error boundary. pub type Element = Option; - /// A [`Component`] is a function that takes a [`Scope`] and returns an [`Element`]. + /// A [`Component`] is a function that takes [`Properties`] and returns an [`Element`]. /// /// Components can be used in other components with two syntax options: /// - lowercase as a function call with named arguments (rust style) @@ -84,7 +84,7 @@ pub use crate::innerlude::{ /// The purpose of this module is to alleviate imports of many common types /// -/// This includes types like [`Scope`], [`Element`], and [`Component`]. +/// This includes types like [`Element`], and [`Component`]. pub mod prelude { pub use crate::innerlude::{ consume_context, consume_context_from_scope, current_scope_id, fc_to_builder, flush_sync, diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index 75ce4ffc7..b45a4ecaa 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -24,7 +24,7 @@ use std::{any::Any, collections::BTreeSet, rc::Rc}; /// /// ## Guide /// -/// Components are defined as simple functions that take [`Scope`] and return an [`Element`]. +/// Components are defined as simple functions that take [`crate::properties::Properties`] and return an [`Element`]. /// /// ```rust /// # use dioxus::prelude::*; @@ -218,7 +218,7 @@ impl VirtualDom { /// # Example /// ```rust, ignore /// fn Example() -> Element { - /// rsx!( div { "hello world" } )) + /// rsx!( div { "hello world" } ) /// } /// /// let dom = VirtualDom::new(Example); @@ -526,7 +526,7 @@ impl VirtualDom { /// /// # Example /// ```rust, ignore - /// static app: Component = |cx| rsx!{ "hello world" }); + /// static app: Component = |cx| rsx!{ "hello world" }; /// /// let mut dom = VirtualDom::new(); /// let edits = dom.rebuild(); diff --git a/packages/dioxus/Cargo.toml b/packages/dioxus/Cargo.toml index fa1d2a4f6..b808bdc85 100644 --- a/packages/dioxus/Cargo.toml +++ b/packages/dioxus/Cargo.toml @@ -55,6 +55,9 @@ warp = ["dioxus-fullstack?/warp", "ssr", "dioxus-liveview?/warp"] rocket = ["dioxus-liveview?/rocket"] tui = ["dioxus-tui", "dioxus-config-macro/tui"] +# This feature enables some nightly flags that make it more clear what structs/methods are available in each feature +nightly-doc = [] + [dev-dependencies] futures-util = { workspace = true } tracing = { workspace = true } diff --git a/packages/dioxus/README.md b/packages/dioxus/README.md index 210ea77c3..ebd2cdb90 100644 --- a/packages/dioxus/README.md +++ b/packages/dioxus/README.md @@ -50,7 +50,7 @@ fn main() { // It's not required, but highly recommended. For example, UpperCamelCase components will not generate a warning. #[component] fn App() -> Element { - rsx!("hello world!")) + rsx!("hello world!") } ``` @@ -97,13 +97,12 @@ If we want to omit the boilerplate of `cx.render`, we can simply pass in render nodes in match statements. ```rust, ignore -#[component[ +#[component] fn Example() -> Element { - // both of these are equivalent - rsx!("hello world")) + rsx!("hello world"); - rsx!("hello world!") + rsx!("hello world!"); } ``` @@ -127,7 +126,7 @@ fn App() -> Element { )) } - )) + ) } ``` @@ -147,7 +146,7 @@ fn App() -> Element { title: "My App", color: "red", } - )) + ) } ``` @@ -169,7 +168,7 @@ fn Header(cx: Scope) -> Element { background_color: "{cx.props.color}" h1 { "{cx.props.title}" } } - )) + ) } ``` @@ -184,7 +183,7 @@ fn Header(title: String, color: String) -> Element { background_color: "{color}" h1 { "{title}" } } - )) + ) } ``` @@ -201,13 +200,13 @@ struct HeaderProps<'a> { } #[component] -fn Header(props: HeaderProps -> Element { +fn Header(props: HeaderProps) -> Element { rsx!( div { background_color: "{cx.props.color}" h1 { "{cx.props.title}" } } - )) + ) } ``` @@ -299,7 +298,7 @@ fn App() -> Element { div { "Count: {count}" } button { onclick: move |_| count.set(count + 1), "Increment" } button { onclick: move |_| count.set(count - 1), "Decrement" } - )) + ) } ``` diff --git a/packages/dioxus/src/launch.rs b/packages/dioxus/src/launch.rs index 3b49eb97a..63b2183e2 100644 --- a/packages/dioxus/src/launch.rs +++ b/packages/dioxus/src/launch.rs @@ -38,6 +38,7 @@ impl LaunchBuilder { /// Launch your web application. #[cfg(feature = "web")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "web")))] pub fn web() -> LaunchBuilder { LaunchBuilder { launch_fn: dioxus_web::launch::launch, @@ -48,6 +49,7 @@ impl LaunchBuilder { /// Launch your desktop application. #[cfg(feature = "desktop")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "desktop")))] pub fn desktop() -> LaunchBuilder { LaunchBuilder { launch_fn: dioxus_desktop::launch::launch, @@ -58,6 +60,7 @@ impl LaunchBuilder { /// Launch your fullstack application. #[cfg(feature = "fullstack")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "fullstack")))] pub fn fullstack() -> LaunchBuilder { LaunchBuilder { launch_fn: dioxus_fullstack::launch::launch, @@ -68,6 +71,7 @@ impl LaunchBuilder { /// Launch your fullstack application. #[cfg(feature = "mobile")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "mobile")))] pub fn mobile() -> LaunchBuilder { LaunchBuilder { launch_fn: dioxus_mobile::launch::launch, @@ -77,6 +81,7 @@ impl LaunchBuilder { } #[cfg(feature = "tui")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "tui")))] /// Launch your tui application pub fn tui() -> LaunchBuilder { LaunchBuilder { @@ -209,24 +214,28 @@ pub fn launch(app: fn() -> Element) { } #[cfg(feature = "web")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "web")))] /// Launch your web application without any additional configuration. See [`LaunchBuilder`] for more options. pub fn launch_web(app: fn() -> Element) { LaunchBuilder::web().launch(app) } #[cfg(feature = "desktop")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "desktop")))] /// Launch your desktop application without any additional configuration. See [`LaunchBuilder`] for more options. pub fn launch_desktop(app: fn() -> Element) { LaunchBuilder::desktop().launch(app) } #[cfg(feature = "fullstack")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "fullstack")))] /// Launch your fullstack application without any additional configuration. See [`LaunchBuilder`] for more options. pub fn launch_fullstack(app: fn() -> Element) { LaunchBuilder::fullstack().launch(app) } #[cfg(feature = "tui")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "tui")))] /// Launch your tui application without any additional configuration. See [`LaunchBuilder`] for more options. pub fn launch_tui(app: fn() -> Element) { LaunchBuilder::tui().launch(app) diff --git a/packages/dioxus/src/lib.rs b/packages/dioxus/src/lib.rs index fd052dfc2..d843cfd56 100644 --- a/packages/dioxus/src/lib.rs +++ b/packages/dioxus/src/lib.rs @@ -1,88 +1,114 @@ #![doc = include_str!("../README.md")] #![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")] #![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")] +#![cfg_attr(any(docsrs, feature = "nightly-doc"), feature(doc_cfg))] pub use dioxus_core; #[cfg(feature = "launch")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "launch")))] mod launch; #[cfg(feature = "hooks")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "hooks")))] pub use dioxus_hooks as hooks; #[cfg(feature = "signals")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "signals")))] pub use dioxus_signals as signals; pub mod events { #[cfg(feature = "html")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "html")))] pub use dioxus_html::prelude::*; } #[cfg(feature = "html")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "html")))] pub use dioxus_html as html; #[cfg(feature = "macro")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "macro")))] pub use dioxus_core_macro as core_macro; pub mod prelude { #[cfg(feature = "launch")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "launch")))] pub use crate::launch::*; #[cfg(feature = "hooks")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "hooks")))] pub use crate::hooks::*; #[cfg(feature = "signals")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "signals")))] pub use dioxus_signals::*; pub use dioxus_core::prelude::*; #[cfg(feature = "macro")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "macro")))] #[allow(deprecated)] pub use dioxus_core_macro::{component, format_args_f, inline_props, render, rsx, Props}; #[cfg(feature = "launch")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "launch")))] pub use dioxus_config_macro::*; #[cfg(feature = "html")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "html")))] pub use dioxus_html as dioxus_elements; #[cfg(feature = "html")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "html")))] pub use dioxus_elements::{prelude::*, GlobalAttributes, SvgAttributes}; #[cfg(all(not(target_arch = "wasm32"), feature = "hot-reload"))] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "hot-reload")))] pub use dioxus_hot_reload::{self, hot_reload_init}; pub use dioxus_core; #[cfg(feature = "fullstack")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "fullstack")))] pub use dioxus_fullstack::prelude::*; #[cfg(feature = "router")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "router")))] pub use dioxus_router; #[cfg(feature = "router")] + #[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "router")))] pub use dioxus_router::prelude::*; } #[cfg(feature = "web")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "web")))] pub use dioxus_web as web; #[cfg(feature = "router")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "router")))] pub use dioxus_router as router; #[cfg(feature = "fullstack")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "fullstack")))] pub use dioxus_fullstack as fullstack; #[cfg(feature = "desktop")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "desktop")))] pub use dioxus_desktop as desktop; #[cfg(feature = "mobile")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "mobile")))] pub use dioxus_desktop as mobile; #[cfg(feature = "liveview")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "liveview")))] pub use dioxus_liveview as liveview; #[cfg(feature = "tui")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "tui")))] pub use dioxus_tui as tui; #[cfg(feature = "ssr")] +#[cfg_attr(any(docsrs, feature = "nightly-doc"), doc(cfg(feature = "ssr")))] pub use dioxus_ssr as ssr; From 7a53dc20d83d8d55f20a344fe2cf6fc66671e8bd Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 9 Feb 2024 12:30:36 -0600 Subject: [PATCH 35/43] deploy nightly rust docs to dioxuslab.com/api-docs/nightly --- .github/workflows/docs.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 7a365dceb..ca68acd9e 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -30,3 +30,8 @@ jobs: with: branch: gh-pages-docs folder: target/doc + target-folder: api-docs/nightly + repository-name: dioxuslabs/docsite + clean: false + token: ${{ secrets.DEPLOY_KEY }} # let's pretend I don't need it for now + From 002de62e0c4fc95897ed708de4e00d331daca7d0 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 9 Feb 2024 12:31:53 -0600 Subject: [PATCH 36/43] fix the docsite branch --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index ca68acd9e..2f93f9de5 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -28,7 +28,7 @@ jobs: - name: Deploy uses: JamesIves/github-pages-deploy-action@v4.5.0 with: - branch: gh-pages-docs + branch: gh-pages folder: target/doc target-folder: api-docs/nightly repository-name: dioxuslabs/docsite From af6467baebe2753565cf4d2e9d794ef0158e023a Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 9 Feb 2024 12:57:03 -0600 Subject: [PATCH 37/43] update cargo.toml to fix ahash dependency issue --- Cargo.lock | 173 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 125 insertions(+), 48 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3477f46ca..427495b02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -326,13 +326,13 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" +checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" dependencies = [ "concurrent-queue", - "event-listener 4.0.3", - "event-listener-strategy", + "event-listener 5.0.0", + "event-listener-strategy 0.5.0", "futures-core", "pin-project-lite", ] @@ -445,7 +445,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" dependencies = [ "event-listener 4.0.3", - "event-listener-strategy", + "event-listener-strategy 0.4.0", "pin-project-lite", ] @@ -1170,9 +1170,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.14.2" +version = "1.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea31d69bda4949c1c1562c1e6f042a1caefac98cdc8a298260a2ff41c1e2d42b" +checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" [[package]] name = "byteorder" @@ -1308,9 +1308,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" +checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" dependencies = [ "serde", ] @@ -1427,9 +1427,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.6" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6100bc57b6209840798d95cb2775684849d332f7bd788db2a8c8caf7ef82a41a" +checksum = "fa50868b64a9a6fda9d593ce778849ea8715cd2a3d2cc17ffdb4a2f2f2f1961d" dependencies = [ "smallvec", "target-lexicon", @@ -3237,6 +3237,17 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "event-listener" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b72557800024fabbaa2449dd4bf24e37b93702d457a4d4f2b0dd1f0f039f20c1" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + [[package]] name = "event-listener-strategy" version = "0.4.0" @@ -3247,6 +3258,16 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "event-listener-strategy" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +dependencies = [ + "event-listener 5.0.0", + "pin-project-lite", +] + [[package]] name = "execute" version = "0.2.13" @@ -4695,6 +4716,29 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "hoot" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df22a4d90f1b0e65fe3e0d6ee6a4608cc4d81f4b2eb3e670f44bb6bde711e452" +dependencies = [ + "httparse", + "log", +] + +[[package]] +name = "hootbin" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "354e60868e49ea1a39c44b9562ad207c4259dc6eabf9863bf3b0f058c55cfdb2" +dependencies = [ + "fastrand 2.0.1", + "hoot", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "hostname" version = "0.3.1" @@ -5248,12 +5292,12 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" +checksum = "fe8f25ce1159c7740ff0b9b2f5cdf4a8428742ba7c112b9f20f22cd5219c7dab" dependencies = [ "hermit-abi 0.3.5", - "rustix 0.38.31", + "libc", "windows-sys 0.52.0", ] @@ -5359,9 +5403,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" dependencies = [ "libc", ] @@ -5790,15 +5834,6 @@ dependencies = [ "imgref", ] -[[package]] -name = "lru" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909" -dependencies = [ - "hashbrown 0.12.3", -] - [[package]] name = "lru" version = "0.10.1" @@ -6460,19 +6495,18 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" dependencies = [ "autocfg", "num-integer", @@ -6493,9 +6527,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", "libm", @@ -7929,7 +7963,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots", + "webpki-roots 0.25.4", "winreg", ] @@ -8345,10 +8379,24 @@ checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", "ring 0.17.7", - "rustls-webpki", + "rustls-webpki 0.101.7", "sct", ] +[[package]] +name = "rustls" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" +dependencies = [ + "log", + "ring 0.17.7", + "rustls-pki-types", + "rustls-webpki 0.102.2", + "subtle", + "zeroize", +] + [[package]] name = "rustls-native-certs" version = "0.6.3" @@ -8370,6 +8418,12 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pki-types" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a716eb65e3158e90e17cd93d855216e27bde02745ab842f2cab4a39dba1bacf" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -8380,6 +8434,17 @@ dependencies = [ "untrusted 0.9.0", ] +[[package]] +name = "rustls-webpki" +version = "0.102.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +dependencies = [ + "ring 0.17.7", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -8796,9 +8861,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.6.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b0ed1662c5a68664f45b76d18deb0e234aff37207086803165c961eb695e981" +checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270" dependencies = [ "base64 0.21.7", "chrono", @@ -8806,6 +8871,7 @@ dependencies = [ "indexmap 1.9.3", "indexmap 2.2.2", "serde", + "serde_derive", "serde_json", "serde_with_macros", "time", @@ -8813,9 +8879,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.6.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "568577ff0ef47b879f736cd66740e022f3672788cdf002a05a4e609ea5a6fb15" +checksum = "865f9743393e638991566a8b7a479043c2c8da94a33e0a31f18214c9cae0a64d" dependencies = [ "darling", "proc-macro2", @@ -9069,11 +9135,11 @@ dependencies = [ [[package]] name = "sledgehammer_utils" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cd16550f1dd7866c7580dbf80c892dc1bef106737eeb850d42c62ec61896059" +checksum = "f20798defa0e9d4eff9ca451c7f84774c7378a9c3b5a40112cfa2b3eadb97ae2" dependencies = [ - "lru 0.8.1", + "lru 0.12.2", "once_cell", "rustc-hash", ] @@ -9256,7 +9322,7 @@ dependencies = [ "tracing", "url", "uuid", - "webpki-roots", + "webpki-roots 0.25.4", ] [[package]] @@ -9626,7 +9692,7 @@ version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2d580ff6a20c55dfb86be5f9c238f67835d0e81cbdea8bf5680e0897320331" dependencies = [ - "cfg-expr 0.15.6", + "cfg-expr 0.15.7", "heck 0.4.1", "pkg-config", "toml 0.8.10", @@ -10640,18 +10706,20 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.9.1" +version = "2.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" +checksum = "0b52731d03d6bb2fd18289d4028aee361d6c28d44977846793b994b13cdcc64d" dependencies = [ "base64 0.21.7", + "hootbin", "log", "native-tls", "once_cell", - "rustls 0.21.10", - "rustls-webpki", + "rustls 0.22.2", + "rustls-pki-types", + "rustls-webpki 0.102.2", "url", - "webpki-roots", + "webpki-roots 0.26.1", ] [[package]] @@ -11164,6 +11232,15 @@ version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +[[package]] +name = "webpki-roots" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webview2-com" version = "0.28.0" From a44f5fda2c046f12d8158392ae974e88f78cb7fc Mon Sep 17 00:00:00 2001 From: Anatol Ulrich Date: Fri, 9 Feb 2024 22:09:58 +0100 Subject: [PATCH 38/43] remove unused `element` field from WebDragData --- packages/web/src/event.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/web/src/event.rs b/packages/web/src/event.rs index b6aa63077..8fa2b1aea 100644 --- a/packages/web/src/event.rs +++ b/packages/web/src/event.rs @@ -49,10 +49,7 @@ impl HtmlEventConverter for WebEventConverter { #[inline(always)] fn convert_drag_data(&self, event: &dioxus_html::PlatformEventData) -> dioxus_html::DragData { let event = downcast_event(event); - DragData::new(WebDragData::new( - event.element.clone(), - event.raw.clone().unchecked_into(), - )) + DragData::new(WebDragData::new(event.raw.clone().unchecked_into())) } #[inline(always)] @@ -462,13 +459,12 @@ impl HasFileData for WebFormData { } struct WebDragData { - element: Element, raw: MouseEvent, } impl WebDragData { - fn new(element: Element, raw: MouseEvent) -> Self { - Self { element, raw } + fn new(raw: MouseEvent) -> Self { + Self { raw } } } From 8bc76c47cab815172282bc03b32fc1858d781d49 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 9 Feb 2024 16:02:48 -0600 Subject: [PATCH 39/43] pin nightly version to fix https://github.com/tkaitchuck/aHash/issues/200 --- .github/workflows/docs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 2f93f9de5..dca1f95be 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -16,6 +16,8 @@ jobs: - run: sudo apt-get update - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev - uses: dtolnay/rust-toolchain@nightly + with: + toolchain: nightly-2024-02-01 - uses: Swatinem/rust-cache@v2 with: cache-all-crates: "true" From 5462c98d4f1b40a01da9adf19f0ada8ad7baf54c Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 9 Feb 2024 16:20:24 -0600 Subject: [PATCH 40/43] Use the default token for the docs workflow --- .github/workflows/docs.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index dca1f95be..6175f4cb5 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -35,5 +35,3 @@ jobs: target-folder: api-docs/nightly repository-name: dioxuslabs/docsite clean: false - token: ${{ secrets.DEPLOY_KEY }} # let's pretend I don't need it for now - From 2e65e7a91352e29f966c0f74be0f3e6bde88edc4 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 9 Feb 2024 16:33:33 -0600 Subject: [PATCH 41/43] restore deploy key for cross repo deploys --- .github/workflows/docs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6175f4cb5..578b1a3c5 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -35,3 +35,4 @@ jobs: target-folder: api-docs/nightly repository-name: dioxuslabs/docsite clean: false + token: ${{ secrets.DEPLOY_KEY }} From 8e007cc137a2210a3a0b47177b55e4b850bbb12e Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Sun, 11 Feb 2024 13:35:34 -0600 Subject: [PATCH 42/43] fix the web renderer panicing when the hot reload connection fails --- packages/web/src/lib.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/web/src/lib.rs b/packages/web/src/lib.rs index 7e365d89b..324b3a8a9 100644 --- a/packages/web/src/lib.rs +++ b/packages/web/src/lib.rs @@ -61,10 +61,7 @@ pub use crate::cfg::Config; #[cfg(feature = "file_engine")] pub use crate::file_engine::WebFileEngineExt; use dioxus_core::VirtualDom; -use futures_util::{ - future::{select, Either}, - pin_mut, FutureExt, StreamExt, -}; +use futures_util::{pin_mut, select, FutureExt, StreamExt}; mod cfg; mod dom; @@ -159,17 +156,21 @@ pub async fn run(virtual_dom: VirtualDom, web_config: Config) { let (mut res, template) = { let work = dom.wait_for_work().fuse(); pin_mut!(work); + let mut rx_next = rx.select_next_some(); #[cfg(all(feature = "hot_reload", debug_assertions))] - match select(work, select(hotreload_rx.next(), rx.next())).await { - Either::Left((_, _)) => (None, None), - Either::Right((Either::Left((new_template, _)), _)) => (None, new_template), - Either::Right((Either::Right((evt, _)), _)) => (evt, None), + { + let mut hot_reload_next = hotreload_rx.select_next_some(); + select! { + _ = work => (None, None), + new_template = hot_reload_next => (None, Some(new_template)), + evt = rx_next => (Some(evt), None), + } } #[cfg(not(all(feature = "hot_reload", debug_assertions)))] - match select(work, rx.next()).await { - Either::Left((_, _)) => (None, None), - Either::Right((evt, _)) => (evt, None), + select! { + _ = work => (None, None), + evt = rx_next => (Some(evt), None), } }; From 476b2ac88ac254ed3b599f1c87b6c41b4977fb71 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Mon, 12 Feb 2024 08:56:27 -0600 Subject: [PATCH 43/43] fix client side suspense --- packages/core/src/virtual_dom.rs | 2 +- packages/web/src/lib.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index b45a4ecaa..2de7f0514 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -439,7 +439,7 @@ impl VirtualDom { self.process_events(); // Now that we have collected all queued work, we should check if we have any dirty scopes. If there are not, then we can poll any queued futures - if !self.dirty_scopes.is_empty() || !self.suspended_scopes.is_empty() { + if !self.dirty_scopes.is_empty() { return; } diff --git a/packages/web/src/lib.rs b/packages/web/src/lib.rs index 324b3a8a9..e106a9dc3 100644 --- a/packages/web/src/lib.rs +++ b/packages/web/src/lib.rs @@ -162,9 +162,9 @@ pub async fn run(virtual_dom: VirtualDom, web_config: Config) { { let mut hot_reload_next = hotreload_rx.select_next_some(); select! { - _ = work => (None, None), - new_template = hot_reload_next => (None, Some(new_template)), - evt = rx_next => (Some(evt), None), + _ = work => (None, None), + new_template = hot_reload_next => (None, Some(new_template)), + evt = rx_next => (Some(evt), None), } } #[cfg(not(all(feature = "hot_reload", debug_assertions)))]