Compare commits

..

2 Commits
v0.8.9 ... 4300

Author SHA1 Message Date
autofix-ci[bot]
da7c29eaf1 [autofix.ci] apply automated fixes 2025-09-17 13:34:44 +00:00
Greg Johnston
937df93770 fix: support const generic static strs on nightly versions with conflicting feature names (closes #4300) 2025-09-17 09:02:00 -04:00
16 changed files with 33 additions and 221 deletions

12
Cargo.lock generated
View File

@@ -1796,7 +1796,7 @@ checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
[[package]]
name = "leptos"
version = "0.8.9"
version = "0.8.8"
dependencies = [
"any_spawner",
"base64",
@@ -2004,7 +2004,7 @@ dependencies = [
[[package]]
name = "leptos_router"
version = "0.8.7"
version = "0.8.6"
dependencies = [
"any_spawner",
"either_of",
@@ -2754,7 +2754,7 @@ dependencies = [
[[package]]
name = "reactive_graph"
version = "0.2.7"
version = "0.2.6"
dependencies = [
"any_spawner",
"async-lock",
@@ -3291,7 +3291,7 @@ dependencies = [
[[package]]
name = "server_fn"
version = "0.8.7"
version = "0.8.6"
dependencies = [
"actix-web",
"actix-ws",
@@ -3581,7 +3581,7 @@ dependencies = [
[[package]]
name = "tachys"
version = "0.2.8"
version = "0.2.7"
dependencies = [
"any_spawner",
"async-trait",
@@ -4367,7 +4367,7 @@ dependencies = [
[[package]]
name = "wasm_split_macros"
version = "0.1.3"
version = "0.1.2"
dependencies = [
"base16",
"digest",

View File

@@ -50,28 +50,28 @@ any_spawner = { path = "./any_spawner/", version = "0.3.0" }
const_str_slice_concat = { path = "./const_str_slice_concat", version = "0.1" }
either_of = { path = "./either_of/", version = "0.1.6" }
hydration_context = { path = "./hydration_context", version = "0.3.0" }
leptos = { path = "./leptos", version = "0.8.9" }
leptos = { path = "./leptos", version = "0.8.8" }
leptos_config = { path = "./leptos_config", version = "0.8.7" }
leptos_dom = { path = "./leptos_dom", version = "0.8.6" }
leptos_hot_reload = { path = "./leptos_hot_reload", version = "0.8.5" }
leptos_integration_utils = { path = "./integrations/utils", version = "0.8.5" }
leptos_macro = { path = "./leptos_macro", version = "0.8.8" }
leptos_router = { path = "./router", version = "0.8.7" }
leptos_router = { path = "./router", version = "0.8.6" }
leptos_router_macro = { path = "./router_macro", version = "0.8.5" }
leptos_server = { path = "./leptos_server", version = "0.8.5" }
leptos_meta = { path = "./meta", version = "0.8.5" }
next_tuple = { path = "./next_tuple", version = "0.1.0" }
oco_ref = { path = "./oco", version = "0.2.1" }
or_poisoned = { path = "./or_poisoned", version = "0.1.0" }
reactive_graph = { path = "./reactive_graph", version = "0.2.7" }
reactive_graph = { path = "./reactive_graph", version = "0.2.6" }
reactive_stores = { path = "./reactive_stores", version = "0.2.5" }
reactive_stores_macro = { path = "./reactive_stores_macro", version = "0.2.6" }
server_fn = { path = "./server_fn", version = "0.8.7" }
server_fn = { path = "./server_fn", version = "0.8.6" }
server_fn_macro = { path = "./server_fn_macro", version = "0.8.7" }
server_fn_macro_default = { path = "./server_fn/server_fn_macro_default", version = "0.8.5" }
tachys = { path = "./tachys", version = "0.2.8" }
tachys = { path = "./tachys", version = "0.2.7" }
wasm_split_helpers = { path = "./wasm_split", version = "0.1.2" }
wasm_split_macros = { path = "./wasm_split_macros", version = "0.1.3" }
wasm_split_macros = { path = "./wasm_split_macros", version = "0.1.2" }
# members deps
async-once-cell = { default-features = false, version = "0.5.3" }

View File

@@ -1,9 +0,0 @@
@check_issue_4285
Feature: Check that issue 4285 does not reappear
Scenario: Navigating several times to same lazy route does not cause issues.
Given I see the app
And I can access regression test 4285
And I can access regression test 4285
And I can access regression test 4285
Then I see the result is the string 42

View File

@@ -1,18 +0,0 @@
@check_issue_4296
Feature: Check that issue 4296 does not reappear
Scenario: Query param signals created in LazyRoute::data() are reactive in ::view().
Given I see the app
And I can access regression test 4296
Then I see the result is the string None
When I select the link abc
Then I see the result is the string Some("abc")
When I select the link def
Then I see the result is the string Some("def")
Scenario: Loading page with query signal works as well.
Given I see the app
And I can access regression test 4296
When I select the link abc
When I reload the page
Then I see the result is the string Some("abc")

View File

@@ -1,7 +1,6 @@
use crate::{
issue_4005::Routes4005, issue_4088::Routes4088, issue_4217::Routes4217,
issue_4285::Routes4285, issue_4296::Routes4296, pr_4015::Routes4015,
pr_4091::Routes4091,
pr_4015::Routes4015, pr_4091::Routes4091,
};
use leptos::prelude::*;
use leptos_meta::{MetaTags, *};
@@ -32,11 +31,9 @@ pub fn shell(options: LeptosOptions) -> impl IntoView {
pub fn App() -> impl IntoView {
provide_meta_context();
let fallback = || view! { "Page not found." }.into_view();
let (_, set_is_routing) = signal(false);
view! {
<Stylesheet id="leptos" href="/pkg/regression.css"/>
<Router set_is_routing>
<Router>
<main>
<Routes fallback>
<Route path=path!("") view=HomePage/>
@@ -45,8 +42,6 @@ pub fn App() -> impl IntoView {
<Routes4088/>
<Routes4217/>
<Routes4005/>
<Routes4285/>
<Routes4296/>
</Routes>
</main>
</Router>
@@ -71,8 +66,6 @@ fn HomePage() -> impl IntoView {
<li><a href="/4088/">"4088"</a></li>
<li><a href="/4217/">"4217"</a></li>
<li><a href="/4005/">"4005"</a></li>
<li><a href="/4285/">"4285"</a></li>
<li><a href="/4296/">"4296"</a></li>
</ul>
</nav>
}

View File

@@ -1,49 +0,0 @@
use leptos::prelude::*;
use leptos_router::LazyRoute;
#[allow(unused_imports)]
use leptos_router::{
components::Route, path, Lazy, MatchNestedRoutes, NavigateOptions,
};
#[component]
pub fn Routes4285() -> impl MatchNestedRoutes + Clone {
view! {
<Route path=path!("4285") view={Lazy::<Issue4285>::new()}/>
}
.into_inner()
}
struct Issue4285 {
data: Resource<Result<i32, ServerFnError>>,
}
impl LazyRoute for Issue4285 {
fn data() -> Self {
Self {
data: Resource::new(|| (), |_| slow_call()),
}
}
async fn view(this: Self) -> AnyView {
let Issue4285 { data } = this;
view! {
<Suspense>
{move || {
Suspend::new(async move {
let data = data.await;
view! {
<p id="result">{data}</p>
}
})
}}
</Suspense>
}
.into_any()
}
}
#[server]
async fn slow_call() -> Result<i32, ServerFnError> {
tokio::time::sleep(std::time::Duration::from_millis(250)).await;
Ok(42)
}

View File

@@ -1,36 +0,0 @@
use leptos::prelude::*;
#[allow(unused_imports)]
use leptos_router::{
components::Route, path, Lazy, MatchNestedRoutes, NavigateOptions,
};
use leptos_router::{hooks::use_query_map, LazyRoute};
#[component]
pub fn Routes4296() -> impl MatchNestedRoutes + Clone {
view! {
<Route path=path!("4296") view={Lazy::<Issue4296>::new()}/>
}
.into_inner()
}
struct Issue4296 {
query: Signal<Option<String>>,
}
impl LazyRoute for Issue4296 {
fn data() -> Self {
let query = use_query_map();
let query = Signal::derive(move || query.read().get("q"));
Self { query }
}
async fn view(this: Self) -> AnyView {
let Issue4296 { query } = this;
view! {
<a href="?q=abc">"abc"</a>
<a href="?q=def">"def"</a>
<p id="result">{move || format!("{:?}", query.get())}</p>
}
.into_any()
}
}

View File

@@ -2,8 +2,6 @@ pub mod app;
mod issue_4005;
mod issue_4088;
mod issue_4217;
mod issue_4285;
mod issue_4296;
mod pr_4015;
mod pr_4091;

View File

@@ -1,6 +1,6 @@
[package]
name = "leptos"
version = "0.8.9"
version = "0.8.8"
authors = ["Greg Johnston"]
license = "MIT"
repository = "https://github.com/leptos-rs/leptos"

View File

@@ -1,6 +1,6 @@
[package]
name = "reactive_graph"
version = "0.2.7"
version = "0.2.6"
authors = ["Greg Johnston"]
license = "MIT"
readme = "../README.md"

View File

@@ -1,6 +1,6 @@
[package]
name = "leptos_router"
version = "0.8.7"
version = "0.8.6"
authors = ["Greg Johnston", "Ben Wishovich"]
license = "MIT"
readme = "../README.md"

View File

@@ -26,7 +26,7 @@ use reactive_graph::{
computed::{ArcMemo, ScopedFuture},
owner::{provide_context, use_context, Owner},
signal::{ArcRwSignal, ArcTrigger},
traits::{Get, GetUntracked, Notify, ReadUntracked, Set, Track, Write},
traits::{Get, GetUntracked, Notify, ReadUntracked, Set, Track},
transition::AsyncTransition,
wrappers::write::SignalSetter,
};
@@ -119,7 +119,6 @@ where
base,
&mut loaders,
&mut outlets,
&outer_owner,
);
drop(url);
@@ -160,14 +159,13 @@ where
}
return;
}
// since the path didn't match, we'll update the retained path for future diffing
state.path.clear();
state.path.push_str(url_snapshot.path());
let new_match = self.routes.match_route(url_snapshot.path());
*state.current_url.write_untracked() = url_snapshot;
state.current_url.set(url_snapshot);
match new_match {
None => {
@@ -194,7 +192,6 @@ where
&mut state.outlets,
self.set_is_routing.is_some(),
0,
&self.outer_owner,
);
let (abort_handle, abort_registration) =
@@ -372,7 +369,6 @@ where
base,
&mut loaders,
&mut outlets,
&outer_owner,
);
// outlets will not send their views if the loaders are never polled
@@ -426,16 +422,8 @@ where
base,
&mut loaders,
&mut outlets,
&outer_owner,
);
let preload_owners = outlets
.iter()
.map(|o| o.preload_owner.clone())
.collect::<Vec<_>>();
outer_owner
.with(|| Owner::on_cleanup(move || drop(preload_owners)));
// outlets will not send their views if the loaders are never polled
// the loaders are async so that they can lazy-load routes in the browser,
// but they should always be synchronously available on the server
@@ -487,7 +475,6 @@ where
base,
&mut loaders,
&mut outlets,
&outer_owner,
);
drop(url);
@@ -543,7 +530,6 @@ where
base,
&mut loaders,
&mut outlets,
&outer_owner,
);
drop(url);
@@ -580,7 +566,6 @@ pub(crate) struct RouteContext {
base: Option<Oco<'static, str>>,
view_fn: Arc<Mutex<OutletViewFn>>,
owner: Arc<Mutex<Option<Owner>>>,
preload_owner: Owner,
child: ChildRoute,
}
@@ -612,7 +597,6 @@ impl Clone for RouteContext {
view_fn: Arc::clone(&self.view_fn),
owner: Arc::clone(&self.owner),
child: self.child.clone(),
preload_owner: self.preload_owner.clone(),
}
}
}
@@ -624,7 +608,6 @@ trait AddNestedRoute {
base: Option<Oco<'static, str>>,
loaders: &mut Vec<Pin<Box<dyn Future<Output = ArcTrigger>>>>,
outlets: &mut Vec<RouteContext>,
outer_owner: &Owner,
);
#[allow(clippy::too_many_arguments)]
@@ -638,7 +621,6 @@ trait AddNestedRoute {
outlets: &mut Vec<RouteContext>,
set_is_routing: bool,
level: u8,
outer_owner: &Owner,
) -> u8;
}
@@ -652,7 +634,6 @@ where
base: Option<Oco<'static, str>>,
loaders: &mut Vec<Pin<Box<dyn Future<Output = ArcTrigger>>>>,
outlets: &mut Vec<RouteContext>,
outer_owner: &Owner,
) {
let orig_url = url;
@@ -720,7 +701,6 @@ where
base: base.clone(),
child: ChildRoute(Arc::new(Mutex::new(None))),
owner: Arc::new(Mutex::new(None)),
preload_owner: outer_owner.child(),
};
if !outlets.is_empty() {
let prev_index = outlets.len().saturating_sub(1);
@@ -745,15 +725,7 @@ where
provide_context(params.clone());
provide_context(url.clone());
provide_context(matched.clone());
outlet
.preload_owner
.with(|| {
provide_context(params.clone());
provide_context(url.clone());
provide_context(matched.clone());
ScopedFuture::new(view.preload())
})
.await;
view.preload().await;
let child = outlet.child.clone();
*view_fn.lock().or_poisoned() =
Box::new(move |owner_where_used| {
@@ -800,13 +772,7 @@ where
// this is important because to build the view, we need access to the outlet
// and the outlet will be returned from building this child
if let Some(child) = child {
child.build_nested_route(
orig_url,
base,
loaders,
outlets,
outer_owner,
);
child.build_nested_route(orig_url, base, loaders, outlets);
}
}
@@ -821,7 +787,6 @@ where
outlets: &mut Vec<RouteContext>,
set_is_routing: bool,
level: u8,
outer_owner: &Owner,
) -> u8 {
let (parent_params, parent_matches): (Vec<_>, Vec<_>) = outlets
.iter()
@@ -838,13 +803,7 @@ where
match current {
// if there's nothing currently in the routes at this point, build from here
None => {
self.build_nested_route(
url,
base,
preloaders,
outlets,
outer_owner,
);
self.build_nested_route(url, base, preloaders, outlets);
level
}
Some(current) => {
@@ -884,10 +843,6 @@ where
&mut current.matched,
ArcRwSignal::new(new_match),
);
let old_preload_owner = mem::replace(
&mut current.preload_owner,
outer_owner.child(),
);
let matched_including_parents = {
ArcMemo::new({
let matched = current.matched.clone();
@@ -930,26 +885,11 @@ where
let child = outlet.child.clone();
async move {
let child = child.clone();
outlet
.preload_owner
.with(|| {
provide_context(
params_including_parents.clone(),
);
provide_context(url.clone());
provide_context(matched.clone());
ScopedFuture::new(async {
if set_is_routing {
AsyncTransition::run(|| {
view.preload()
})
.await;
} else {
view.preload().await;
}
})
})
.await;
if set_is_routing {
AsyncTransition::run(|| view.preload()).await;
} else {
view.preload().await;
}
*view_fn.lock().or_poisoned() =
Box::new(move |owner_where_used| {
let prev_owner = route_owner
@@ -998,7 +938,6 @@ where
drop(old_params);
drop(old_url);
drop(old_matched);
drop(old_preload_owner);
trigger
}
})));
@@ -1009,13 +948,8 @@ where
// if this children has matches, then rebuild the lower section of the tree
if let Some(child) = child {
child.build_nested_route(
url,
base,
preloaders,
outlets,
outer_owner,
);
child
.build_nested_route(url, base, preloaders, outlets);
} else {
*outlets[*items].child.0.lock().or_poisoned() = None;
}
@@ -1039,7 +973,6 @@ where
outlets,
set_is_routing,
level + 1,
outer_owner,
)
} else {
*current.child.0.lock().or_poisoned() = None;

View File

@@ -5,7 +5,7 @@ license = "MIT"
repository = "https://github.com/leptos-rs/leptos"
description = "RPC for any web framework."
readme = "../README.md"
version = "0.8.7"
version = "0.8.6"
rust-version.workspace = true
edition.workspace = true

View File

@@ -1,6 +1,6 @@
[package]
name = "tachys"
version = "0.2.8"
version = "0.2.7"
authors = ["Greg Johnston"]
license = "MIT"
readme = "../README.md"

View File

@@ -227,7 +227,7 @@ html_self_closing_elements! {
html_elements! {
/// The `<a>` HTML element (or anchor element), with its href attribute, creates a hyperlink to web pages, files, email addresses, locations in the same page, or anything else a URL can address.
a HtmlAnchorElement [download, href, hreflang, ping, referrerpolicy, rel, target, r#type ] true,
a HtmlAnchorElement [download, href, hreflang, ping, rel, target, r#type ] true,
/// The `<abbr>` HTML element represents an abbreviation or acronym; the optional title attribute can provide an expansion or description for the abbreviation. If present, title must contain this full description and nothing else.
abbr HtmlElement [] true,
/// The `<address>` HTML element indicates that the enclosed HTML provides contact information for a person or people, or for an organization.

View File

@@ -1,6 +1,6 @@
[package]
name = "wasm_split_macros"
version = "0.1.3"
version = "0.1.2"
authors = ["Greg Johnston"]
license = "MIT"
readme = "README.md"