From 28d1856dd722910b63b7cfb37750108c924c778a Mon Sep 17 00:00:00 2001 From: slhx agent Date: Mon, 1 Jun 2026 20:08:17 +0200 Subject: [PATCH] fix(js): reload stale popstate partials When back/forward navigation receives an incompatible or unusable partial response, reload the current URL instead of leaving the previous UI stale. req: page_swap/005 req: page_swap/006 req: runtime/004 --- slhx-js/runtime/slhx.js | 5 +++-- slhx-js/tests/runtime.rs | 11 ++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/slhx-js/runtime/slhx.js b/slhx-js/runtime/slhx.js index e36e7c5..9e7a6a6 100644 --- a/slhx-js/runtime/slhx.js +++ b/slhx-js/runtime/slhx.js @@ -180,8 +180,9 @@ headers: { "X-SLHX-Partial": "1", "Accept": "text/html" }, credentials: "same-origin", }); - if (!await applyResponse(response, root) && mode !== "none") { - location.href = href; + if (!await applyResponse(response, root)) { + if (mode === "none") location.reload(); + else location.href = href; return; } if (mode === "push") history.pushState({ slhx: true }, "", href); diff --git a/slhx-js/tests/runtime.rs b/slhx-js/tests/runtime.rs index bfb1ce4..cfb80b1 100644 --- a/slhx-js/tests/runtime.rs +++ b/slhx-js/tests/runtime.rs @@ -145,7 +145,16 @@ fn runtime_exposes_page_swap_hooks() { assert!(source.contains("x-slhx-title")); assert!(source.contains("x-slhx-fingerprint")); assert!(source.contains("slhx:missing-content-slot")); - assert!(source.contains("location.href = href")); + assert!(source.contains("else location.href = href")); +} + +#[test] +fn runtime_popstate_failed_partials_reload_instead_of_stale_ui() { + // req: page_swap/005 req: page_swap/006 req: runtime/004 + let source = slhx_js::RUNTIME_JS; + + assert!(source.contains("if (mode === \"none\") location.reload();")); + assert!(source.contains("if (root) navigateUrl(location.href, root, \"none\")")); } #[test]