Rollup merge of #112707 - GuillaumeGomez:back-in-history-fix, r=notriddle

[rustdoc] Fix invalid handling of "going back in history" when "go to only search result" setting is enabled

You can test the fix [here](https://rustdoc.crud.net/imperio/back-in-history-fix/lib2/index.html). Enable "Directly go to item in search if there is only one result", then search for `HasALongTraitWithParams` and finally go back to previous page. It should be back on the `index.html` page.

The reason for this bug is that the JS state is cached as is, so when we go back to the page, it resumes where it was left, somewhat (very weird), meaning the search is run again etc. The best way to handle this is to force the JS re-execution in this case so that it doesn't try to resume from where it left and then lead us back to the current page.

r? ``@notriddle``
This commit is contained in:
Matthias Krüger 2023-06-17 12:43:31 +02:00 committed by GitHub
commit 63799ba549
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 20 deletions

View file

@ -277,14 +277,18 @@ function preLoadCss(cssUrl) {
searchState.mouseMovedAfterSearch = false;
document.title = searchState.title;
},
hideResults: () => {
switchDisplayedElement(null);
removeQueryParameters: () => {
// We change the document title.
document.title = searchState.titleBeforeSearch;
// We also remove the query parameter from the URL.
if (browserSupportsHistoryApi()) {
history.replaceState(null, "", getNakedUrl() + window.location.hash);
}
},
hideResults: () => {
switchDisplayedElement(null);
// We also remove the query parameter from the URL.
searchState.removeQueryParameters();
},
getQueryStringParams: () => {
const params = {};
window.location.search.substring(1).split("&").

View file

@ -2071,6 +2071,20 @@ function initSearch(rawSearchIndex) {
if (go_to_first || (results.others.length === 1
&& getSettingValue("go-to-only-result") === "true")
) {
// Needed to force re-execution of JS when coming back to a page. Let's take this
// scenario as example:
//
// 1. You have the "Directly go to item in search if there is only one result" option
// enabled.
// 2. You make a search which results only one result, leading you automatically to
// this result.
// 3. You go back to previous page.
//
// Now, without the call below, the JS will not be re-executed and the previous state
// will be used, starting search again since the search input is not empty, leading you
// back to the previous page again.
window.onunload = () => {};
searchState.removeQueryParameters();
const elem = document.createElement("a");
elem.href = results.others[0].href;
removeClass(elem, "active");
@ -2185,6 +2199,18 @@ function initSearch(rawSearchIndex) {
printTab(currentTab);
}
function updateSearchHistory(url) {
if (!browserSupportsHistoryApi()) {
return;
}
const params = searchState.getQueryStringParams();
if (!history.state && !params.search) {
history.pushState(null, "", url);
} else {
history.replaceState(null, "", url);
}
}
/**
* Perform a search based on the current state of the search input element
* and display the results.
@ -2195,7 +2221,6 @@ function initSearch(rawSearchIndex) {
if (e) {
e.preventDefault();
}
const query = parseQuery(searchState.input.value.trim());
let filterCrates = getFilterCrates();
@ -2221,15 +2246,7 @@ function initSearch(rawSearchIndex) {
// Because searching is incremental by character, only the most
// recent search query is added to the browser history.
if (browserSupportsHistoryApi()) {
const newURL = buildUrl(query.original, filterCrates);
if (!history.state && !params.search) {
history.pushState(null, "", newURL);
} else {
history.replaceState(null, "", newURL);
}
}
updateSearchHistory(buildUrl(query.original, filterCrates));
showResults(
execQuery(query, searchWords, filterCrates, window.currentCrate),
@ -2695,13 +2712,8 @@ function initSearch(rawSearchIndex) {
function updateCrate(ev) {
if (ev.target.value === "all crates") {
// If we don't remove it from the URL, it'll be picked up again by the search.
const params = searchState.getQueryStringParams();
const query = searchState.input.value.trim();
if (!history.state && !params.search) {
history.pushState(null, "", buildUrl(query, null));
} else {
history.replaceState(null, "", buildUrl(query, null));
}
updateSearchHistory(buildUrl(query, null));
}
// In case you "cut" the entry from the search input, then change the crate filter
// before paste back the previous search, you get the old search results without

View file

@ -34,7 +34,14 @@ go-to: "file://" + |DOC_PATH| + "/lib2/index.html"
// We enter it into the search.
write: (".search-input", "HasALongTraitWithParams")
wait-for-document-property: {"title": "HasALongTraitWithParams in lib2 - Rust"}
assert-document-property: ({"URL": "/lib2/struct.HasALongTraitWithParams.html"}, ENDS_WITH)
assert-window-property: ({"location": "/lib2/struct.HasALongTraitWithParams.html"}, ENDS_WITH)
// Regression test for <https://github.com/rust-lang/rust/issues/112676>.
// If "go-to-only-result" is enabled and you go back to history, it should not lead you back to the
// page result again automatically.
history-go-back:
wait-for-document-property: {"title": "lib2 - Rust"}
assert-window-property: ({"location": "/lib2/index.html"}, ENDS_WITH)
// We try again to see if it goes to the only result
go-to: "file://" + |DOC_PATH| + "/lib2/index.html?search=HasALongTraitWithParams"