You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Change { replace: true } to { history: "replace" }
We can then introduce { history: "push" } which explicitly errors if we're in a convert-to-replace situation. Closes#111.
This also fixes a preexisting omission where we were not properly doing replace navigations before the document is loaded.
@@ -225,7 +225,7 @@ The current entry can be replaced with a new entry, with a new `NavigationHistor
225
225
226
226
- Via `history.replaceState()`.
227
227
228
-
- Via cross-document replace navigations generated by `location.replace()` or `navigation.navigate(url, { replace:true, ... })`. Note that if the navigation is cross-origin, then we'll end up in a separate navigation API history entry list for that other origin, where `key` will not be preserved.
228
+
- Via cross-document replace navigations generated by `location.replace()` or `navigation.navigate(url, { history:"replace", ... })`. Note that if the navigation is cross-origin, then we'll end up in a separate navigation API history entry list for that other origin, where `key` will not be preserved.
229
229
230
230
- When using the `navigate` event to [convert a cross-document replace navigation into a same-document navigation](#navigation-monitoring-and-interception).
231
231
@@ -445,7 +445,7 @@ navigation.addEventListener("navigate", e => {
445
445
awaitfetch("/form-submit", { body:e.formData });
446
446
447
447
// Perform a client-side "redirect" to /destination.
@@ -746,22 +746,24 @@ Note how unlike `history.pushState()`, `navigation.navigate()` will by default p
746
746
747
747
Regardless of whether the navigation gets converted or not, calling `navigation.navigate()`inthis form will clear any future entries in the joint session history. (This includes entries coming from frame navigations, or cross-origin entries: so, it can have an impact beyond just the `navigation.entries()` list.)
748
748
749
-
`navigation.navigate()` also takes a `replace` option, which indicates that it will replace the current history entry in a similar manner to `location.replace()`. It is used as follows:
749
+
`navigation.navigate()` also takes a `history` option, which controls whether the navigation will replace the current history entry in a similar manner to `location.replace()`. It is used as follows:
750
750
751
751
```js
752
752
// Performs a navigation to the given URL, but replace the current history entry
753
753
// instead of pushing a new one.
754
754
// (equivalent to `location.replace(url)`)
755
-
navigation.navigate(url, { replace: true });
755
+
navigation.navigate(url, { history: "replace" });
756
756
757
757
// Replace the URL and state at the same time.
758
-
navigation.navigate(url, { replace: true, state });
758
+
navigation.navigate(url, { history: "replace", state });
759
759
760
760
// You can still pass along info:
761
-
navigation.navigate(url, { replace: true, state, info });
761
+
navigation.navigate(url, { history: "replace", state, info });
762
762
```
763
763
764
-
Again, unlike `history.replaceState()`, `navigation.navigate(url, { replace: true })` will by default perform a full navigation. And again, single-page apps will usually intercept these using `navigate`.
764
+
Again, unlike `history.replaceState()`, `navigation.navigate(url, { history: "replace" })` will by default perform a full navigation. And again, single-page apps will usually intercept these using `navigate`.
765
+
766
+
There are two other values the `history` option can take:`"auto"`, which will usually perform a push navigation but will perform a replace navigation under special circumstances (such as when on the initial `about:blank`document or when navigating to the current URL); and `"push"`, which will always either perform a push navigation or fail if called under those special circumstances. Most developers will be fine either omitting the `history`option (which has `"auto"` behavior) or using `"replace"`.
765
767
766
768
Finally, we have `navigation.reload()`. This can be used as a replacement for`location.reload()`, but it also allows passing `info` and `state`, which are useful when a single-page app intercepts the reload using the `navigate`event:
767
769
@@ -993,7 +995,7 @@ This can be useful for cleaning up any information in secondary stores, such as
993
995
994
996
### Current entry change monitoring
995
997
996
-
The `window.navigation` object has an event, `currententrychange`, which allows the application to react to any updates to the `navigation.currentEntry` property. This includes both navigations that change its value to a new `NavigationHistoryEntry`, and calls to APIs like `history.replaceState()`, `navigation.updateCurrentEntry()`, or intercepted `navigation.navigate(url, { replace: true, state: newState })` calls that change its state or URL.
998
+
The `window.navigation` object has an event, `currententrychange`, which allows the application to react to any updates to the `navigation.currentEntry` property. This includes both navigations that change its value to a new `NavigationHistoryEntry`, and calls to APIs like `history.replaceState()`, `navigation.updateCurrentEntry()`, or intercepted `navigation.navigate(url, { history: "replace", state: newState })` calls that change its state or URL.
997
999
998
1000
Unlike `navigate`, this event occurs *after* the navigation is committed. As such, it cannot be intercepted or canceled; it's just an after-the-fact notification.
999
1001
@@ -1094,7 +1096,7 @@ For web developers using the API, here's a guide to explain how you would replac
1094
1096
1095
1097
Instead of using `history.pushState(state, "", url)`, use `navigation.navigate(url, { state })` and combine it with a `navigate` handler to convert the default cross-document navigation into a same-document navigation.
1096
1098
1097
-
Instead of using `history.replaceState(state, "", url)`, use `navigation.navigate(url, { replace: true, state })`, again combined with a `navigate` handler. Note that if you omit the state value, i.e. if you say `navigation.navigate(url, { replace: true })`, then this will overwrite the entry's state with`undefined`.
1099
+
Instead of using `history.replaceState(state, "", url)`, use `navigation.navigate(url, { history: "replace", state })`, again combined with a `navigate` handler. Note that if you omit the state value, i.e. if you say `navigation.navigate(url, { history: "replace" })`, then this will overwrite the entry's state with`undefined`.
1098
1100
1099
1101
Instead of using `history.back()` and `history.forward()`, use `navigation.back()` and `navigation.forward()`. Note that unlike the `history` APIs, the `navigation` APIs will ignore other frames when determining where to navigate to. This means it might move through multiple entries in the joint session history, skipping over any entries that were generated purely by other-frame navigations.
Each {{Navigation}} object has an associated <dfn for="Navigation">entry list</dfn>, a [=list=] of {{NavigationHistoryEntry}} objects, initially empty.
@@ -750,7 +756,7 @@ An <dfn>navigation API method navigation</dfn> is a [=struct=] with the followin
750
756
<dd>
751
757
<p>Navigates the current page to the given <var ignore>url</var>. <var ignore>options</var> can contain the following values:
752
758
753
-
* {{NavigationNavigateOptions/replace}} can be set to true to replace the current session history entry, instead of pushing a new one.
759
+
* {{NavigationNavigateOptions/history}} can be set to "{{NavigationHistoryBehavior/replace}}" to replace the current session history entry, instead of pushing a new one.
754
760
* {{NavigationOptions/info}} can be set to any value; it will populate the {{NavigateEvent/info}} property of the corresponding {{Navigation/navigate}} event.
755
761
* {{NavigationNavigateOptions/state}} can be set to any [=serializable object|serializable=] value; it will populate the state retrieved by {{NavigationHistoryEntry/getState()|navigation.currentEntry.getState()}} once the navigation completes, for same-document navigations. (It will be ignored for navigations that end up cross-document.)
756
762
@@ -787,6 +793,23 @@ An <dfn>navigation API method navigation</dfn> is a [=struct=] with the followin
787
793
788
794
1. <a spec="HTML" lt="parse a URL">Parse</a> |url| relative to [=this=]'s [=relevant settings object=]. If that returns failure, then return [=an early error result=] for a "{{SyntaxError}}" {{DOMException}}. Otherwise, let |urlRecord| be the <a spec="HTML">resulting URL record</a>.
789
795
796
+
1. Let |document| be [=this=]'s [=relevant global object=]'s [=associated document=].
797
+
798
+
1. If |options|["{{NavigationNavigateOptions/history}}"] is "{{NavigationHistoryBehavior/push}}", and any of the following are true:
799
+
800
+
* |document|'s <a spec="HTML">is initial about:blank</a> is true;
801
+
* |document| is not <a spec="HTML">completely loaded</a>;
802
+
* |url| equals |document|'s [=Document/URL=]; or
803
+
* |url|'s [=url/scheme=] is "`javascript`"
804
+
805
+
then return [=an early error result=] for a "{{NotSupportedError}}" {{DOMException}}.
806
+
807
+
<div class="note">
808
+
<p>These are the conditions under which a push navigation will be converted into a replace navigation by the <a spec="HTML">navigate</a> algorithm or by the below step. If the developer explicitly requested a push, we fail to let them know it won't happen.
809
+
810
+
<p>In the future, we could consider loosening some of these conditions, e.g., allowing explicitly-requested push navigations to the current URL or before the document is completely loaded.
811
+
</div>
812
+
790
813
1. Let |serializedState| be null.
791
814
792
815
1. If |options|["{{NavigationNavigateOptions/state}}"][=map/exists=], then set |serializedState| to [$StructuredSerializeForStorage$](|options|["{{NavigationNavigateOptions/state}}"]). If this throws an exception, then return [=an early error result=] for that exception.
@@ -795,7 +818,7 @@ An <dfn>navigation API method navigation</dfn> is a [=struct=] with the followin
795
818
796
819
1. Let |info| be |options|["{{NavigationOptions/info}}"] if it exists; otherwise, undefined.
797
820
798
-
1. Let |historyHandling| be "<a for="history handling behavior">`replace`</a>" if |options|["{{NavigationNavigateOptions/replace}}"] is true; otherwise, "<a for="history handling behavior">`default`</a>".
821
+
1. Let |historyHandling| be "<a for="history handling behavior">`replace`</a>" if |options|["{{NavigationNavigateOptions/history}}"] is "{{NavigationHistoryBehavior/replace}}" or if |document| is not <a spec="HTML">completely loaded</a>; otherwise, "<a for="history handling behavior">`default`</a>".
799
822
800
823
1. Return the result of [=performing a non-traverse navigation API navigation=] given [=this=], |urlRecord|, |serializedState|, |info|, and |historyHandling|.
0 commit comments