From 855a3c65c0ee3f0e3d74eeb05e0844adab498fec Mon Sep 17 00:00:00 2001 From: Greg Johnston Date: Sat, 6 Jan 2024 18:25:20 -0500 Subject: [PATCH 1/4] chore: remove newly-detected unused tuple fields (#2169) --- leptos_reactive/src/runtime.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/leptos_reactive/src/runtime.rs b/leptos_reactive/src/runtime.rs index 9099a2bff6..c4860f909f 100644 --- a/leptos_reactive/src/runtime.rs +++ b/leptos_reactive/src/runtime.rs @@ -951,12 +951,11 @@ impl RuntimeId { false }; - let prev_observer = - SetObserverOnDrop(self, runtime.observer.take()); + let prev_observer = SetObserverOnDrop(runtime.observer.take()); untracked_result = f(); - runtime.observer.set(prev_observer.1); + runtime.observer.set(prev_observer.0); std::mem::forget(prev_observer); // avoid Drop #[cfg(debug_assertions)] @@ -1371,12 +1370,12 @@ impl std::hash::Hash for Runtime { } } -struct SetObserverOnDrop(RuntimeId, Option); +struct SetObserverOnDrop(Option); impl Drop for SetObserverOnDrop { fn drop(&mut self) { _ = with_runtime(|rt| { - rt.observer.set(self.1); + rt.observer.set(self.0); }); } } @@ -1393,14 +1392,13 @@ impl Drop for SetObserverOnDrop { )] #[inline(always)] pub fn batch(f: impl FnOnce() -> T) -> T { - let runtime_id = Runtime::current(); with_runtime(move |runtime| { - let batching = SetBatchingOnDrop(runtime_id, runtime.batching.get()); + let batching = SetBatchingOnDrop(runtime.batching.get()); runtime.batching.set(true); let val = f(); - runtime.batching.set(batching.1); + runtime.batching.set(batching.0); std::mem::forget(batching); runtime.run_effects(); @@ -1409,12 +1407,12 @@ pub fn batch(f: impl FnOnce() -> T) -> T { .expect("tried to run a batched update in a runtime that has been disposed") } -struct SetBatchingOnDrop(RuntimeId, bool); +struct SetBatchingOnDrop(bool); impl Drop for SetBatchingOnDrop { fn drop(&mut self) { _ = with_runtime(|rt| { - rt.batching.set(self.1); + rt.batching.set(self.0); }); } } From f5bf539148c7ec137e6c9d62c4097e14044a04af Mon Sep 17 00:00:00 2001 From: Simon Bihel Date: Sun, 7 Jan 2024 20:28:50 +0000 Subject: [PATCH 2/4] fix: allow multiple SSRed Leptos apps on same server (closes #1806) (#2135) --- router/src/components/router.rs | 14 +++++++++- router/src/components/routes.rs | 45 +++++++++++++++++++++------------ router/src/matching/mod.rs | 22 +++++++++++----- 3 files changed, 57 insertions(+), 24 deletions(-) diff --git a/router/src/components/router.rs b/router/src/components/router.rs index 5de3ad1c0b..0238821303 100644 --- a/router/src/components/router.rs +++ b/router/src/components/router.rs @@ -8,11 +8,17 @@ use cfg_if::cfg_if; use leptos::*; #[cfg(feature = "transition")] use leptos_reactive::use_transition; -use std::{cell::RefCell, rc::Rc}; +use std::{ + cell::RefCell, + rc::Rc, + sync::atomic::{AtomicUsize, Ordering}, +}; use thiserror::Error; #[cfg(not(feature = "ssr"))] use wasm_bindgen::JsCast; +static GLOBAL_ROUTERS_COUNT: AtomicUsize = AtomicUsize::new(0); + /// Provides for client-side and server-side routing. This should usually be somewhere near /// the root of the application. #[component] @@ -51,6 +57,7 @@ pub struct RouterContext { pub(crate) inner: Rc, } pub(crate) struct RouterContextInner { + id: usize, pub location: Location, pub base: RouteContext, pub possible_routes: RefCell>>, @@ -165,6 +172,7 @@ impl RouterContext { }); let inner = Rc::new(RouterContextInner { + id: GLOBAL_ROUTERS_COUNT.fetch_add(1, Ordering::SeqCst), base_path: base_path.into_owned(), path_stack: store_value(vec![location.pathname.get_untracked()]), location, @@ -203,6 +211,10 @@ impl RouterContext { self.inner.base.clone() } + pub(crate) fn id(&self) -> usize { + self.inner.id + } + /// A list of all possible routes this router can match. pub fn possible_branches(&self) -> Vec { self.inner diff --git a/router/src/components/routes.rs b/router/src/components/routes.rs index 5ce76a8e7e..d94419618a 100644 --- a/router/src/components/routes.rs +++ b/router/src/components/routes.rs @@ -8,6 +8,7 @@ use crate::{ }; use leptos::{leptos_dom::HydrationCtx, *}; use std::{ + borrow::Cow, cell::{Cell, RefCell}, cmp::Reverse, collections::HashMap, @@ -76,15 +77,16 @@ pub fn Routes( ) -> impl IntoView { let router = use_context::() .expect(" component should be nested within a ."); + let router_id = router.id(); let base_route = router.base(); let base = base.unwrap_or_default(); - Branches::initialize(&base, children()); + Branches::initialize(router_id, &base, children()); #[cfg(feature = "ssr")] if let Some(context) = use_context::() { - Branches::with(&base, |branches| { + Branches::with(router_id, &base, |branches| { *context.0.borrow_mut() = branches.to_vec() }); } @@ -93,7 +95,8 @@ pub fn Routes( let current_route = next_route; let root_equal = Rc::new(Cell::new(true)); - let route_states = route_states(base, &router, current_route, &root_equal); + let route_states = + route_states(router_id, base, &router, current_route, &root_equal); provide_context(route_states); let id = HydrationCtx::id(); @@ -156,15 +159,16 @@ pub fn AnimatedRoutes( ) -> impl IntoView { let router = use_context::() .expect(" component should be nested within a ."); + let router_id = router.id(); let base_route = router.base(); let base = base.unwrap_or_default(); - Branches::initialize(&base, children()); + Branches::initialize(router_id, &base, children()); #[cfg(feature = "ssr")] if let Some(context) = use_context::() { - Branches::with(&base, |branches| { + Branches::with(router_id, &base, |branches| { *context.0.borrow_mut() = branches.to_vec() }); } @@ -193,8 +197,9 @@ pub fn AnimatedRoutes( let prev_matches = prev .map(|(_, r)| r) .cloned() - .map(|location| get_route_matches(&base, location)); - let matches = get_route_matches(&base, next_route.clone()); + .map(|location| get_route_matches(router_id, &base, location)); + let matches = + get_route_matches(router_id, &base, next_route.clone()); let same_route = prev_matches .and_then(|p| p.first().as_ref().map(|r| r.route.key.clone())) == matches.first().as_ref().map(|r| r.route.key.clone()); @@ -221,7 +226,8 @@ pub fn AnimatedRoutes( let current_route = create_memo(move |_| animation_and_route.get().1); let root_equal = Rc::new(Cell::new(true)); - let route_states = route_states(base, &router, current_route, &root_equal); + let route_states = + route_states(router_id, base, &router, current_route, &root_equal); let root = root_route(base_route, route_states, root_equal); let node_ref = create_node_ref::(); @@ -266,12 +272,13 @@ pub fn AnimatedRoutes( pub(crate) struct Branches; +type BranchesCacheKey = (usize, Cow<'static, str>); thread_local! { - static BRANCHES: RefCell>> = RefCell::new(HashMap::new()); + static BRANCHES: RefCell>> = RefCell::new(HashMap::new()); } impl Branches { - pub fn initialize(base: &str, children: Fragment) { + pub fn initialize(router_id: usize, base: &str, children: Fragment) { BRANCHES.with(|branches| { #[cfg(debug_assertions)] { @@ -286,7 +293,7 @@ impl Branches { } let mut current = branches.borrow_mut(); - if !current.contains_key(base) { + if !current.contains_key(&(router_id, Cow::from(base))) { let mut branches = Vec::new(); let children = children .as_children() @@ -316,15 +323,19 @@ impl Branches { true, base, ); - current.insert(base.to_string(), branches); + current.insert((router_id, Cow::Owned(base.into())), branches); } }) } - pub fn with(base: &str, cb: impl FnOnce(&[Branch]) -> T) -> T { + pub fn with( + router_id: usize, + base: &str, + cb: impl FnOnce(&[Branch]) -> T, + ) -> T { BRANCHES.with(|branches| { let branches = branches.borrow(); - let branches = branches.get(base).expect( + let branches = branches.get(&(router_id, Cow::from(base))).expect( "Branches::initialize() should be called before \ Branches::with()", ); @@ -334,14 +345,16 @@ impl Branches { } fn route_states( + router_id: usize, base: String, router: &RouterContext, current_route: Memo, root_equal: &Rc>, ) -> Memo { // whenever path changes, update matches - let matches = - create_memo(move |_| get_route_matches(&base, current_route.get())); + let matches = create_memo(move |_| { + get_route_matches(router_id, &base, current_route.get()) + }); // iterate over the new matches, reusing old routes when they are the same // and replacing them with new routes when they differ diff --git a/router/src/matching/mod.rs b/router/src/matching/mod.rs index 554e67c1ea..584b6c9028 100644 --- a/router/src/matching/mod.rs +++ b/router/src/matching/mod.rs @@ -17,6 +17,7 @@ pub(crate) struct RouteMatch { } pub(crate) fn get_route_matches( + router_id: usize, base: &str, location: String, ) -> Rc> { @@ -24,24 +25,31 @@ pub(crate) fn get_route_matches( { use lru::LruCache; use std::{cell::RefCell, num::NonZeroUsize}; + type RouteMatchCache = LruCache<(usize, String), Rc>>; thread_local! { - static ROUTE_MATCH_CACHE: RefCell>>> = RefCell::new(LruCache::new(NonZeroUsize::new(32).unwrap())); + static ROUTE_MATCH_CACHE: RefCell = RefCell::new(LruCache::new(NonZeroUsize::new(32).unwrap())); } ROUTE_MATCH_CACHE.with(|cache| { let mut cache = cache.borrow_mut(); - Rc::clone(cache.get_or_insert(location.clone(), || { - build_route_matches(base, location) - })) + Rc::clone( + cache.get_or_insert((router_id, location.clone()), || { + build_route_matches(router_id, base, location) + }), + ) }) } #[cfg(not(feature = "ssr"))] - build_route_matches(base, location) + build_route_matches(router_id, base, location) } -fn build_route_matches(base: &str, location: String) -> Rc> { - Rc::new(Branches::with(base, |branches| { +fn build_route_matches( + router_id: usize, + base: &str, + location: String, +) -> Rc> { + Rc::new(Branches::with(router_id, base, |branches| { for branch in branches { if let Some(matches) = branch.matcher(&location) { return matches; From bbcef811f45f70b6f8cfdcc91a28663ecbb994af Mon Sep 17 00:00:00 2001 From: Paul Hansen Date: Sun, 7 Jan 2024 14:29:15 -0600 Subject: [PATCH 3/4] chore: remove dead code in actix tailwind example (#2160) --- examples/tailwind_actix/src/main.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/examples/tailwind_actix/src/main.rs b/examples/tailwind_actix/src/main.rs index 02b75aa6fd..b94b351d01 100644 --- a/examples/tailwind_actix/src/main.rs +++ b/examples/tailwind_actix/src/main.rs @@ -9,11 +9,6 @@ cfg_if! { use crate::app::*; use leptos_actix::{generate_route_list, LeptosRoutes}; - #[get("/style.css")] - async fn css() -> impl Responder { - actix_files::NamedFile::open_async("./style/output.css").await - } - #[actix_web::main] async fn main() -> std::io::Result<()> { @@ -30,7 +25,6 @@ cfg_if! { let site_root = &leptos_options.site_root; let routes = &routes; App::new() - .service(css) .leptos_routes(leptos_options.to_owned(), routes.to_owned(), || view! { }) .service(Files::new("/", site_root)) .wrap(middleware::Compress::default()) From 2d70229608121232b4787195494465821812e8c1 Mon Sep 17 00:00:00 2001 From: webmstk Date: Sun, 7 Jan 2024 23:29:54 +0300 Subject: [PATCH 4/4] chore: add rust-toolchain.toml to examples (closes #2151) (#2161) --- examples/counter/rust-toolchain.toml | 2 ++ examples/counter_url_query/rust-toolchain.toml | 2 ++ examples/counters/rust-toolchain.toml | 1 - examples/directives/rust-toolchain.toml | 1 - examples/error_boundary/rust-toolchain.toml | 2 ++ examples/errors_axum/README.md | 4 ++++ examples/errors_axum/rust-toolchain.toml | 2 ++ examples/fetch/rust-toolchain.toml | 2 ++ examples/hackernews/rust-toolchain.toml | 2 ++ examples/hackernews_axum/rust-toolchain.toml | 2 ++ examples/hackernews_islands_axum/rust-toolchain.toml | 2 ++ examples/js-framework-benchmark/rust-toolchain.toml | 2 ++ examples/parent_child/rust-toolchain.toml | 1 - examples/router/rust-toolchain.toml | 2 ++ examples/session_auth_axum/rust-toolchain.toml | 2 ++ examples/slots/rust-toolchain.toml | 2 ++ examples/ssr_modes/rust-toolchain.toml | 2 ++ examples/ssr_modes_axum/rust-toolchain.toml | 2 ++ examples/tailwind_axum/rust-toolchain.toml | 1 - examples/tailwind_csr/rust-toolchain.toml | 2 ++ examples/todo_app_sqlite/rust-toolchain.toml | 2 ++ examples/todo_app_sqlite_axum/rust-toolchain.toml | 2 ++ examples/todo_app_sqlite_csr/rust-toolchain.toml | 2 ++ examples/todo_app_sqlite_viz/rust-toolchain.toml | 2 ++ examples/todomvc/rust-toolchain.toml | 2 ++ 25 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 examples/counter/rust-toolchain.toml create mode 100644 examples/counter_url_query/rust-toolchain.toml create mode 100644 examples/error_boundary/rust-toolchain.toml create mode 100644 examples/errors_axum/rust-toolchain.toml create mode 100644 examples/fetch/rust-toolchain.toml create mode 100644 examples/hackernews/rust-toolchain.toml create mode 100644 examples/hackernews_axum/rust-toolchain.toml create mode 100644 examples/hackernews_islands_axum/rust-toolchain.toml create mode 100644 examples/js-framework-benchmark/rust-toolchain.toml create mode 100644 examples/router/rust-toolchain.toml create mode 100644 examples/session_auth_axum/rust-toolchain.toml create mode 100644 examples/slots/rust-toolchain.toml create mode 100644 examples/ssr_modes/rust-toolchain.toml create mode 100644 examples/ssr_modes_axum/rust-toolchain.toml create mode 100644 examples/tailwind_csr/rust-toolchain.toml create mode 100644 examples/todo_app_sqlite/rust-toolchain.toml create mode 100644 examples/todo_app_sqlite_axum/rust-toolchain.toml create mode 100644 examples/todo_app_sqlite_csr/rust-toolchain.toml create mode 100644 examples/todo_app_sqlite_viz/rust-toolchain.toml create mode 100644 examples/todomvc/rust-toolchain.toml diff --git a/examples/counter/rust-toolchain.toml b/examples/counter/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/counter/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/counter_url_query/rust-toolchain.toml b/examples/counter_url_query/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/counter_url_query/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/counters/rust-toolchain.toml b/examples/counters/rust-toolchain.toml index e9743fb495..5d56faf9ae 100644 --- a/examples/counters/rust-toolchain.toml +++ b/examples/counters/rust-toolchain.toml @@ -1,3 +1,2 @@ - [toolchain] channel = "nightly" diff --git a/examples/directives/rust-toolchain.toml b/examples/directives/rust-toolchain.toml index e9743fb495..5d56faf9ae 100644 --- a/examples/directives/rust-toolchain.toml +++ b/examples/directives/rust-toolchain.toml @@ -1,3 +1,2 @@ - [toolchain] channel = "nightly" diff --git a/examples/error_boundary/rust-toolchain.toml b/examples/error_boundary/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/error_boundary/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/errors_axum/README.md b/examples/errors_axum/README.md index af9942f96e..e0e393f15a 100644 --- a/examples/errors_axum/README.md +++ b/examples/errors_axum/README.md @@ -5,3 +5,7 @@ This example demonstrates how Leptos Errors can work with an Axum backend on a s ## Getting Started See the [Examples README](../README.md) for setup and run instructions. + +## Quick Start + +Run `cargo leptos watch` to run this example. diff --git a/examples/errors_axum/rust-toolchain.toml b/examples/errors_axum/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/errors_axum/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/fetch/rust-toolchain.toml b/examples/fetch/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/fetch/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/hackernews/rust-toolchain.toml b/examples/hackernews/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/hackernews/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/hackernews_axum/rust-toolchain.toml b/examples/hackernews_axum/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/hackernews_axum/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/hackernews_islands_axum/rust-toolchain.toml b/examples/hackernews_islands_axum/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/hackernews_islands_axum/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/js-framework-benchmark/rust-toolchain.toml b/examples/js-framework-benchmark/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/js-framework-benchmark/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/parent_child/rust-toolchain.toml b/examples/parent_child/rust-toolchain.toml index e9743fb495..5d56faf9ae 100644 --- a/examples/parent_child/rust-toolchain.toml +++ b/examples/parent_child/rust-toolchain.toml @@ -1,3 +1,2 @@ - [toolchain] channel = "nightly" diff --git a/examples/router/rust-toolchain.toml b/examples/router/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/router/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/session_auth_axum/rust-toolchain.toml b/examples/session_auth_axum/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/session_auth_axum/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/slots/rust-toolchain.toml b/examples/slots/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/slots/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/ssr_modes/rust-toolchain.toml b/examples/ssr_modes/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/ssr_modes/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/ssr_modes_axum/rust-toolchain.toml b/examples/ssr_modes_axum/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/ssr_modes_axum/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/tailwind_axum/rust-toolchain.toml b/examples/tailwind_axum/rust-toolchain.toml index e9743fb495..5d56faf9ae 100644 --- a/examples/tailwind_axum/rust-toolchain.toml +++ b/examples/tailwind_axum/rust-toolchain.toml @@ -1,3 +1,2 @@ - [toolchain] channel = "nightly" diff --git a/examples/tailwind_csr/rust-toolchain.toml b/examples/tailwind_csr/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/tailwind_csr/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/todo_app_sqlite/rust-toolchain.toml b/examples/todo_app_sqlite/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/todo_app_sqlite/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/todo_app_sqlite_axum/rust-toolchain.toml b/examples/todo_app_sqlite_axum/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/todo_app_sqlite_axum/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/todo_app_sqlite_csr/rust-toolchain.toml b/examples/todo_app_sqlite_csr/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/todo_app_sqlite_csr/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/todo_app_sqlite_viz/rust-toolchain.toml b/examples/todo_app_sqlite_viz/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/todo_app_sqlite_viz/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" diff --git a/examples/todomvc/rust-toolchain.toml b/examples/todomvc/rust-toolchain.toml new file mode 100644 index 0000000000..5d56faf9ae --- /dev/null +++ b/examples/todomvc/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly"