fix(js): keep the current URL when pushState/replaceState omit url
resolveOrFallback(undefined) returned undefined, so applyVirtual set __virtualUrl to null and location reverted to the document URL. Per the HTML spec a missing url keeps the current document URL; return __currentUrl() so the new history entry captures the current location instead of clearing it. Fixes #496
This commit is contained in:
1 parent
8078cc3070
commit
1fc5a24e98
2 files changed
+26
-1
No files matched your search
Vendored
+4
-1
@@ -5613,7 +5613,10 @@ globalThis.atob = globalThis.atob || ((s) => { const c="ABCDEFGHIJKLMNOPQRSTUVWX
|
|||||||
const stack = [{state: null, url: undefined}]; // initial entry; url=undefined means "use document URL"
|
const stack = [{state: null, url: undefined}]; // initial entry; url=undefined means "use document URL"
|
||||||
let idx = 0;
|
let idx = 0;
|
||||||
const resolveOrFallback = (url) => {
|
const resolveOrFallback = (url) => {
|
||||||
if (url === null || url === undefined) return undefined;
|
// A missing url (pushState/replaceState called with < 3 args) keeps the
|
||||||
|
// current document URL per the HTML spec — capture it so the entry does not
|
||||||
|
// reset location back to the original document URL.
|
||||||
|
if (url === null || url === undefined) return __currentUrl();
|
||||||
try { return new URL(String(url), __currentUrl()).href; } catch (e) { return String(url); }
|
try { return new URL(String(url), __currentUrl()).href; } catch (e) { return String(url); }
|
||||||
};
|
};
|
||||||
const applyVirtual = () => {
|
const applyVirtual = () => {
|
||||||
|
|||||||
@@ -1317,6 +1317,28 @@ mod tests {
|
|||||||
rt
|
rt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn replace_state_without_url_preserves_current_location() {
|
||||||
|
let mut rt = setup_runtime("<html><body></body></html>");
|
||||||
|
let path = rt
|
||||||
|
.evaluate(
|
||||||
|
"(function(){history.pushState({}, '', '/dashboard'); history.replaceState({scroll:1}); return location.pathname;})()",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(path, serde_json::json!("/dashboard"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn push_state_without_url_preserves_current_location() {
|
||||||
|
let mut rt = setup_runtime("<html><body></body></html>");
|
||||||
|
let path = rt
|
||||||
|
.evaluate(
|
||||||
|
"(function(){history.pushState({}, '', '/a'); history.pushState({b:1}); return location.pathname;})()",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(path, serde_json::json!("/a"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_document_title() {
|
fn test_document_title() {
|
||||||
let mut rt = setup_runtime("<html><head><title>Test</title></head><body></body></html>");
|
let mut rt = setup_runtime("<html><head><title>Test</title></head><body></body></html>");
|
||||||
|
|||||||
Reference in new issue
Block a user