From 68f43031fa07bc95ac278da0d4216703fe19333d Mon Sep 17 00:00:00 2001
From: Domenic Denicola The following features are defined in UI Events: Interactive user agents may provide users with a means to follow the hyperlinks created using the [LegacyFactoryFunction]
[LegacyLenientThis]
[LegacyNullToEmptyString]
EventInit
dictionary typetype
attributeis
value
MutationObserver
interface and mutation observers in generalAbortSignal
link
element, somewhere
- within their user interface. The exact interface is not defined by this specification, but it
- could include the following information (obtained from the element's attributes, again as defined
- below), in some form or another (possibly simplified), for each hyperlink created
- with each link
element in the document:browser UI
". The exact interface is not defined by this
+ specification, but it could include the following information (obtained from the element's
+ attributes, again as defined below), in some form or another (possibly simplified), for each
+ hyperlink created with each link
element in the document:
The activation behavior of an a
element element given an
- event event is:
If element has no href
attribute,
- then return.
Let hyperlinkSuffix be null.
If event's target is an
- img
with an ismap
attribute specified,
- then:
Let x and y be 0.
If event's isTrusted
attribute is
- initialized to true, then set x to the distance in CSS
- pixels from the left edge of the image to the location of the click, and set
- y to the distance in CSS pixels from the top edge of the
- image to the location of the click.
If x is negative, set x to 0.
If y is negative, set y to 0.
Set hyperlinkSuffix to the concatenation of U+003F (?), the value of - x expressed as a base-ten integer using ASCII digits, U+002C (,), and - the value of y expressed as a base-ten integer using ASCII - digits.
If element has a download
- attribute, or if the user has expressed a preference to download the hyperlink, then download the hyperlink created by element given
- hyperlinkSuffix.
Otherwise, follow the hyperlink created by - element given hyperlinkSuffix.
When an a
or area
element's activation behavior is
- invoked, the user agent may allow the user to indicate a preference regarding whether the
- hyperlink is to be used for navigation or whether the resource it
- specifies is to be downloaded.
In the absence of a user preference, the default should be navigation if the element has no
- download
attribute, and should be to download the
- specified resource if it does.
Whether determined by the user's preferences or via the presence or absence of the attribute, - if the decision is to use the hyperlink for navigation then the user - agent must follow the hyperlink, and if the decision is - to use the hyperlink to download a resource, the user agent must download the hyperlink. These terms are defined in subsequent sections - below.
-The download
attribute, if present, indicates that the author intends the hyperlink to be used for downloading a resource. The attribute may have a value; the
@@ -23698,7 +23652,6 @@ document.body.appendChild(wbr);
cautioned that most file systems have limitations with regard to what punctuation is supported in
filenames, and user agents are likely to adjust filenames accordingly.
The ping
attribute, if present, gives the URLs of the
resources that are interested in being notified if the user follows the hyperlink. The value must
@@ -23748,6 +23701,76 @@ document.body.appendChild(wbr);
policy attribute. Its purpose is to set the referrer policy used when
following hyperlinks.
When an a
or area
element's activation behavior is
+ invoked, the user agent may allow the user to indicate a preference regarding whether the
+ hyperlink is to be used for navigation or whether the resource it
+ specifies is to be downloaded.
In the absence of a user preference, the default should be navigation if the element has no
+ download
attribute, and should be to download the
+ specified resource if it does.
The activation behavior of an a
or area
element
+ element given an event event is:
If element has no href
attribute,
+ then return.
Let hyperlinkSuffix be null.
If element is an a
element, and event's target is an img
with an ismap
attribute specified, then:
Let x and y be 0.
If event's isTrusted
attribute is
+ initialized to true, then set x to the distance in CSS
+ pixels from the left edge of the image to the location of the click, and set
+ y to the distance in CSS pixels from the top edge of the
+ image to the location of the click.
If x is negative, set x to 0.
If y is negative, set y to 0.
Set hyperlinkSuffix to the concatenation of U+003F (?), the value of + x expressed as a base-ten integer using ASCII digits, U+002C (,), and + the value of y expressed as a base-ten integer using ASCII + digits.
Let userInvolvement be event's user + navigation involvement.
If the user has expressed a preference to download the hyperlink, then set
+ userInvolvement to "browser UI
".
That is, if the user has expressed a specific preference for downloading, this
+ no longer counts as merely "activation
".
If element has a download
+ attribute, or if the user has expressed a preference to download the hyperlink, then download the hyperlink created by element with
+ hyperlinkSuffix set to hyperlinkSuffix
+ and userInvolvement set to
+ userInvolvement.
Otherwise, follow the hyperlink created by + element with hyperlinkSuffix set to + hyperlinkSuffix and userInvolvement set to + userInvolvement.
a
and area
elementsTo follow the hyperlink created by an element - subject, given an optional hyperlinkSuffix (default null):
+ subject, given an optional hyperlinkSuffix (default null) and an + optional userInvolvement (default "none
"):
If subject cannot navigate, then return.
Navigate targetNavigable to url using subject's node document, with referrerPolicy set to referrerPolicy.
+ data-x="navigation-referrer-policy">referrerPolicy set to referrerPolicy and userInvolvement set to userInvolvement.Unlike many other types of navigations, following hyperlinks does not have
special "replace
" behavior for when documents are not
@@ -24387,32 +24414,18 @@ document.body.appendChild(wbr);
The following allowed to download algorithm takes two booleans - sourceAllowsDownloading and targetAllowsDownloading, and returns a boolean - indicating whether or not downloading is allowed:
- -If either sourceAllowsDownloading or targetAllowsDownloading are - false, then return false.
- -Optionally, the user agent may return false, if it believes doing so would safeguard the - user from a potentially hostile download.
Return true.
To download the hyperlink created by an - element subject, given an optional hyperlinkSuffix (default null):
+ element subject, given an optional hyperlinkSuffix (default null) and an + optional userInvolvement (default + "none
"):
If subject cannot navigate, then return.
Let sourceAllowsDownloading be false if subject's node - document's active sandboxing flag set has the sandboxed downloads - browsing context flag set; otherwise true.
If the result of the allowed to download algorithm with - sourceAllowsDownloading and true is false, then return.
If subject's node document's + active sandboxing flag set has the sandboxed downloads browsing context + flag set, then return.
Parse a URL given subject's If parsing the URL fails, then return. Otherwise, let URL be the resulting URL string. Otherwise, let url be the resulting URL string. If hyperlinkSuffix is non-null, then append it to url. If userInvolvement is not " Assert: subject has a Let navigation be subject's relevant global object's
+ navigation API. If hyperlinkSuffix is non-null, then append it to URL. Let filename be the value of subject's Let continue be the result of firing a download request If continue is false, then return. Run these steps in parallel: Optionally, the user agent may abort these steps, if it believes doing so would
+ safeguard the user from a potentially hostile download. Let request be a new request whose
- URL is URL,
+ URL is url,
client is entry settings object,
initiator is " When user agents allow users to follow hyperlinks or
- download hyperlinks created using the
- When user agents allow users to follow hyperlinks
+ or download hyperlinks created using the
+ The activation behavior of an If element has no If element has a Otherwise, follow the hyperlink created by
- element. The IDL attributes The The The activation behavior for The activation behavior for If this element is not mutable and is not in the Checkbox state and is not in the If element is not mutable and is not in the
+ Checkbox state and is not in the Radio state, then return. Run this element's input activation behavior, if any, and do nothing
- otherwise. If element hasinput activation behavior, then run it given
+ event. Recall that an element's activation behavior runs for both
@@ -49098,7 +49125,7 @@ ldh-str = < as defined in If the element's node document is not fully active, then
return. Submit the form owner from the
- element. Submit the element's form owner
+ from the element with userInvolvement set to
+ event's user navigation involvement. Set the element's selected
coordinate to coordinate. Submit the form owner from the
- element. Submit the element's form owner
+ from the element with userInvolvement set to
+ event's user navigation involvement. The selected coordinate must consist of
@@ -51260,7 +51289,8 @@ interface HTMLButtonElement : HTMLElement {
Button state, the element is barred from
constraint validation. A A If element is disabled, then
@@ -51277,7 +51307,9 @@ interface HTMLButtonElement : HTMLElement {
Submit element's form
- owner from element.href
attribute, relative to subject's node
@@ -24420,16 +24433,45 @@ document.body.appendChild(wbr);
browser UI
",
+ then:
+
+ download
attribute.download
attribute.navigate
event at
+ navigation with destinationURL set to url, userInvolvement set to
+ userInvolvement, and filename set
+ to filename.
+
download
",
destination is the empty string, and whose
@@ -40213,14 +40255,14 @@ interface HTMLAreaElement : HTMLElement {
area
element, as described in the next section, the href
, target
, download
, and ping
- attributes decide how the link is followed. The rel
- attribute may be used to indicate to the user the likely nature of the target resource before the
- user follows the link.area
element, the href
, target
, download
, and ping
attributes decide how the link is followed. The rel
attribute may be used to indicate to the user the likely
+ nature of the target resource before the user follows the link.area
element element is:
-
-
href
attribute,
- then return.download
- attribute, or if the user has expressed a preference to download the hyperlink, then download the hyperlink created by
- element.alt
, coords
, HTMLFormElement
: HTMLElement {
submit()
- method, when invoked, must submit the form
- element from the form
element itself, with the submitted from submit()
method flag set.submit()
method set to true.
requestSubmit(submitter)
method, when
@@ -46205,15 +46231,16 @@ interface HTMLInputElement : HTMLElement {
data-x="concept-input-checked-dirty-flag">dirty checkedness flag from the node being cloned
to the copy.input
elements are these steps:input
elements element, given
+ event, are these steps:
-
button
element element's activation behavior is:button
element element's activation behavior given
+ event is:
Reset element's form
@@ -57523,12 +57555,19 @@ fur
If the form has
no submit button, then the implicit submission
- mechanism must do nothing if the form has more than one field that blocks implicit
- submission, and must submit the For the purpose of the previous paragraph, an element is a field that blocks implicit
- submission of a If the form has more than one field that blocks implicit submission, then
+ return. Submit the For the purpose of the previous paragraph, an element is a field that blocks implicit
+ submission of a Each When a To submit a If form cannot navigate, then return.form
- element from the form
element itself otherwise.form
element if it is an input
element whose
+
+
+
+ form
element from the
+ form
element itself with userInvolvement
+ set to "activation
".form
element if it is an input
element whose
form owner is that form
element and whose type
attribute is in one of the following states:
Text,
@@ -57558,11 +57597,13 @@ fur
form
element has a firing submission events boolean, initially
false.form
element form is submitted from an element submitter
- (typically a button), optionally with a submitted from submit()
method flag set, the user agent must run the
- following steps:form
element form
+ from an element submitter (typically a button), given an optional boolean submitted from submit()
method (default false) and an optional
+ user navigation involvement userInvolvement (default "none
"):
has its sandboxed forms browsing context flag set, then return.
If the submitted from submit()
method flag
- is not set, then:
+
If submitted from submit()
method is false,
+ then:
If form's firing submission events is true, then @@ -57733,12 +57774,12 @@ fur defining this, act in a manner analogous to that defined in this specification for similar schemes.
-Each form
element has a planned navigation, which is either null or a
- task; when the form
is first created, its
+
Each form
element has a planned navigation, which is either null or
+ a task; when the form
is first created, its
planned navigation must be set to null. In the behaviors described below, when the
- user agent is required to plan to navigate to a URL url given
- an optional POST resource-or-null postResource (default null), it must
- run the following steps:
Let referrerPolicy be the empty string.
Navigate targetNavigable to url
using the form
element's node document, with historyHandling set to historyHandling, referrerPolicy set to referrerPolicy, documentResource set to postResource, and cspNavigationType set to "form-submission
".
If the value of this OffscreenCanvas
object's [[Detached]]
- internal slot is set to true, then return a promise rejected with an
+ internal slot is set to true, then return a promise rejected with an
"InvalidStateError
" DOMException
.
If this OffscreenCanvas
object's OffscreenCanvas : EventTarget {
promise rejected with a "SecurityError
" DOMException
.
If this OffscreenCanvas
object's bitmap has no pixels (i.e., either its
- horizontal dimension or its vertical dimension is zero) then return a promise rejected with an
+ data-x="offscreencanvas-bitmap">bitmap has no pixels (i.e., either its horizontal
+ dimension or its vertical dimension is zero) then return a promise rejected with an
"IndexSizeError
" DOMException
.
Let bitmap be a copy of this Returns the serialized state of the active session history entry, deserialized into a
- JavaScript value. Returns the classic history API state
+ of the active session history entry, deserialized
+ into a JavaScript value. Adds a new entry into session history with its serialized state set to a serialization of
- data. The active history entry's
+ data-x="she-classic-history-api-state">classic history API stateOffscreenCanvas
object's Window : EventTarget {
attribute DOMString name;
[PutForwards=href, LegacyUnforgeable] readonly attribute Location location;
readonly attribute History history;
+ readonly attribute Navigation navigation;
readonly attribute CustomElementRegistry customElements;
[Replaceable] readonly attribute BarProp locationbar;
[Replaceable] readonly attribute BarProp menubar;
@@ -86210,9 +86253,9 @@ interface History {
history.state
history.go()
history.pushState(data, "")
(The second parameter exists for historical reasons, and cannot be omitted; passing the @@ -86262,8 +86305,8 @@ interface History {
history.pushState(data, "", url)
Adds a new entry into session history with its serialized state set to a serialization of - data, and with its URL set to url.
+ data-x="she-classic-history-api-state">classic history API state set to a serialization + of data, and with its URL set to url.If the current Document
cannot have
its URL rewritten to url, a "SecurityError
"
@@ -86275,9 +86318,9 @@ interface History {
history.replaceState(data, "")
Updates the serialized state of the active session history entry to a structured clone of - data.
+Updates the classic history API state of + the active session history entry to a structured + clone of data.
(The second parameter exists for historical reasons, and cannot be omitted; passing the empty string is traditional.)
@@ -86285,9 +86328,9 @@ interface History {history.replaceState(data, "", url)
Updates the serialized state of the active session history entry to a structured clone of - data, and its URL to url.
+Updates the classic history API state of + the active session history entry to a structured + clone of data, and its URL to url.
If the current Document
cannot have
its URL rewritten to url, a "SecurityError
"
@@ -86399,7 +86442,8 @@ interface History {
Traverse the history by a delta given document's node navigable's traversable navigable, - delta, and document.
The pushState(data,
@@ -86451,6 +86495,20 @@ interface History {
Let navigation be history's relevant global object's + navigation API.
Let continue be the result of firing a push/replace/reload navigate
+ event at navigation with navigationType set to historyHandling,
+ isSameDocument set to true, destinationURL set to newURL, and classicHistoryAPIState set to
+ serializedData.
If continue is false, then return.
+Run the URL and history update steps given document and newURL, with serializedData set to serializedData and historyHandling set to @@ -86670,8 +86728,2064 @@ interface History { +
The navigation API, provided by the global navigation
+ object, provides a modern and web application-focused way of managing same-origin
+ same-navigable history entries and navigations. Its entry point is
+ the Navigation
interface:
[Exposed=Window]
+interface Navigation : EventTarget {
+ sequence<NavigationHistoryEntry> entries();
+ readonly attribute NavigationHistoryEntry? currentEntry;
+ undefined updateCurrentEntry(NavigationUpdateCurrentEntryOptions options);
+ readonly attribute NavigationTransition? transition;
+
+ readonly attribute boolean canGoBack;
+ readonly attribute boolean canGoForward;
+
+ NavigationResult navigate(USVString url, optional NavigationNavigateOptions options = {});
+ NavigationResult reload(optional NavigationReloadOptions options = {});
+
+ NavigationResult traverseTo(DOMString key, optional NavigationOptions options = {});
+ NavigationResult back(optional NavigationOptions options = {});
+ NavigationResult forward(optional NavigationOptions options = {});
+
+ attribute EventHandler onnavigate;
+ attribute EventHandler onnavigatesuccess;
+ attribute EventHandler onnavigateerror;
+ attribute EventHandler oncurrententrychange;
+};
+
+dictionary NavigationUpdateCurrentEntryOptions {
+ required any state;
+};
+
+dictionary NavigationOptions {
+ any info;
+};
+
+dictionary NavigationNavigateOptions : NavigationOptions {
+ any state;
+ NavigationHistoryBehavior history = "auto";
+};
+
+dictionary NavigationReloadOptions : NavigationOptions {
+ any state;
+};
+
+dictionary NavigationResult {
+ Promise<NavigationHistoryEntry> committed;
+ Promise<NavigationHistoryEntry> finished;
+};
+
+enum NavigationHistoryBehavior {
+ "auto",
+ "push",
+ "replace"
+};
+
+ Each Window
has an associated navigation API, which is a Navigation
object. Upon creation of the Window
object, its navigation API must be set to a new Navigation
object created in the Window
object's relevant realm.
The navigation
getter steps are to return this's navigation API.
The following are the event handlers (and their corresponding event handler event types) that must be supported,
+ as event handler IDL attributes, by all objects implementing the
+ Navigation
interface:
Event handler + | Event handler event type + |
---|---|
onnavigate
+ | navigate
+ |
onnavigatesuccess
+ | navigatesuccess
+ |
onnavigateerror
+ | navigateerror
+ |
oncurrententrychange
+ | currententrychange
+ |
Each Navigation
has an associated entry list, a list of NavigationHistoryEntry
objects, initially empty.
Each Navigation
has an associated current entry index, an integer, initially −1.
The current entry of a Navigation
navigation is the result of running the following steps:
If navigation has entries and events disabled, then return null.
Assert: navigation's current entry index is not −1.
Return navigation's entry list[navigation's current entry index].
A Navigation
navigation has entries and events disabled if the following steps return true:
Let document be navigation's relevant global object's associated Document
.
If document is not fully active, then return true.
If document's is initial about:blank
is true, then return true.
If document's origin is opaque, then return true.
Return false.
To get the navigation API entry index of a session history entry she within a Navigation
navigation:
Let index be 0.
For each nhe of navigation's entry list:
+ +If nhe's session history entry is equal to she, then return index.
Increment index by 1.
Return −1.
A key type used throughout the navigation API is the NavigationType
enumeration:
enum NavigationType {
+ "push",
+ "replace",
+ "reload",
+ "traverse"
+};
+
+ This captures the main web developer-visible types of "navigations", which (as noted elsewhere) do not exactly correspond to this standard's singular navigate algorithm. The meaning of each value is the following:
+ +push
"push
", or to history.pushState()
.replace
"replace
", or to history.replaceState()
.reload
"traverse
"The value space of the NavigationType
enumeration is a superset of the value space of the specification-internal history handling behavior type. Several parts of this standard make use of this overlap, by passing in a history handling behavior to an algorithm that expects a NavigationType
.
To initialize the entries for a new Navigation
given a Navigation
navigation, a list of session history entries newSHEs, and a session history entry initialSHE:
Assert: navigation's entry list is empty.
Assert: navigation's current entry index is −1.
If navigation has entries and events disabled, then return.
For each newSHE of newSHEs:
+ +Let newNHE be a new NavigationHistoryEntry
created in the relevant realm of navigation.
Set newNHE's session history entry to newSHE.
Append newNHE to navigation's entry list.
Set navigation's current entry index to the result of getting the navigation API entry index of initialSHE within navigation.
To update the entries for reactivation given a Navigation
navigation, a list of session history entries newSHEs, and a session history entry reactivatedSHE:
If navigation has entries and events disabled, then return.
Let newNHEs be a new empty list.
Let oldNHEs be a clone of navigation's entry list.
For each newSHE of newSHEs:
+ +Let newNHE be null.
If oldNHEs contains a NavigationHistoryEntry
matchingOldNHE whose session history entry is newSHE, then:
Set newNHE to matchingOldNHE.
Remove matchingOldNHE from oldNHEs.
Otherwise:
+ +Set newNHE to a new NavigationHistoryEntry
created in the relevant realm of navigation.
Set newNHE's session history entry to newSHE.
Append newNHE to newNHEs.
By the end of this loop, all NavigationHistoryEntry
s that remain in oldNHEs represent session history entries which have been disposed while the Document
was in bfcache.
Set navigation's entry list to newNHEs.
Set navigation's current entry index to the result of getting the navigation API entry index of reactivatedSHE within navigation.
Queue a global task on the navigation and traversal task source given navigation's relevant global object to run the following steps:
+ +For each disposedNHE of oldNHEs:
+ +Fire an event named dispose
at disposedNHE.
We delay these steps by a task to ensure that dispose
events will fire after the pageshow
event. This ensures that pageshow
is the first event a page receives upon reactivation.
(However, the rest of this algorithm runs before the pageshow
event fires. This ensures that navigation.entries()
and navigation.currentEntry
will have correctly-updated values during any pageshow
event handlers.)
To update the entries for a same-document navigation given a Navigation
navigation, a session history entry destinationSHE, and a NavigationType
navigationType:
If navigation has entries and events disabled, then return.
Let oldCurrentNHE be the current entry of navigation.
Let disposedNHEs be a new empty list.
If navigationType is "traverse
", then:
Set navigation's current entry index to the result of getting the navigation API entry index of destinationSHE within navigation.
Assert: navigation's current entry index is not −1.
This algorithm is only called for same-document traversals. Cross-document traversals will instead call either initialize the entries for a new Navigation
or update the entries for reactivation.
Otherwise, if navigationType is "push
", then:
Set navigation's current entry index to navigation's current entry index + 1.
Let i be navigation's current entry index.
While i < navigation's entry list's size:
+ +Append navigation's entry list[i] to disposedNHEs.
Set i to i + 1.
Remove all items in disposedNHEs from navigation's entry list.
Otherwise, if navigationType is "replace
", then:
Append oldCurrentNHE to disposedNHEs.
If navigationType is "push
" or "replace
", then:
Let newNHE be a new NavigationHistoryEntry
created in the relevant realm of navigation.
Set newNHE's session history entry to destinationSHE.
Set navigation's entry list[navigation's current entry index] to newNHE.
If navigation's ongoing API method tracker is non-null, then notify about the committed-to entry given navigation's ongoing API method tracker and the current entry of navigation.
+ +It is important to do this before firing the dispose
or currententrychange
events, since event handlers could start another navigation, or otherwise change the value of navigation's ongoing API method tracker.
Prepare to run script given navigation's relevant settings object.
+ +See the discussion for other navigation API events to understand why we do this.
+Fire an event named currententrychange
at navigation using NavigationCurrentEntryChangeEvent
, with its navigationType
attribute initialized to navigationType and its from
initialized to oldCurrentNHE.
For each disposedNHE of disposedNHEs:
+ +Fire an event named dispose
at disposedNHE.
Clean up after running script given navigation's relevant settings object.
NavigationHistoryEntry
interface[Exposed=Window]
+interface NavigationHistoryEntry : EventTarget {
+ readonly attribute USVString? url;
+ readonly attribute DOMString key;
+ readonly attribute DOMString id;
+ readonly attribute long long index;
+ readonly attribute boolean sameDocument;
+
+ any getState();
+
+ attribute EventHandler ondispose;
+};
+
+ entry.url
The URL of this navigation history entry.
+ +This can return null if the entry corresponds to a different Document
than the current one (i.e., if sameDocument
is false), and that Document
was fetched with a referrer policy of "no-referrer
" or "origin
", since that indicates the Document
in question is hiding its URL even from other same-origin pages.
entry.key
A user agent-generated random UUID string representing this navigation history entry's place in the navigation history list. This value will be reused by other NavigationHistoryEntry
instances that replace this one due to "replace
" navigations, and will survive reloads and session restores.
This is useful for navigating back to this entry in the navigation hisotyr list, using navigation.traverseTo(key)
.
entry.id
A user agent-generated random UUID string representing this specific navigation history entry. This value will not be reused by other NavigationHistoryEntry
instances. This value will survive reloads and session restores.
This is useful for associating data with this navigation history entry using other storage APIs.
+entry.index
The index of this NavigationHistoryEntry
within navigation.entries()
, or −1 if the entry is not in the navigation history entry list.
entry.sameDocument
Indicates whether or not this navigation history entry is for the same Document
as the current one, or not. This will be true, for example, when the entry represents a fragment navigation or single-page app navigation.
entry.getState()
Returns the deserialization of the state stored in this entry, which was added to the entry using navigation.navigate()
or navigation.updateCurrentEntry()
. This state survives reloads and session restores.
Note that in general, unless the state value is a primitive, entry.getState() !== entry.getState()
, since a fresh deserialization is returned each time.
This state is unrelated to the classic history API's history.state
.
Each NavigationHistoryEntry
has an associated session history entry, which is a session history entry.
The url
getter steps are:
Let document be this's relevant global object's associated Document
.
If document is not fully active, then return the empty string.
Let she be this's session history entry.
If she's document does not equal document, and she's document state's request referrer policy is "no-referrer
" or "origin
", then return null.
Return she's URL, serialized.
The key
getter steps are:
If this's relevant global object's associated Document
is not fully active, then return the empty string.
Return this's session history entry's navigation API key.
The id
getter steps are:
If this's relevant global object's associated Document
is not fully active, then return the empty string.
Return this's session history entry's navigation API ID.
The index
getter steps are:
If this's relevant global object's associated Document
is not fully active, then return the empty string.
Return the result of getting the navigation API entry index of this's session history entry within this's relevant global object's navigation API.
The sameDocument
getter steps are:
Let document be this's relevant global object's associated Document
.
If document is not fully active, then return false.
Return true if this's session history entry's document equals document, and false otherwise.
The getState()
method steps are:
If this's relevant global object's associated Document
is not fully active, then return undefined.
Return StructuredDeserialize(this's session history entry's navigation API state). Rethrow any exceptions.
+ +This can in theory throw an exception, if attempting to deserialize a large ArrayBuffer
when not enough memory is available.
The following are the event handlers (and their corresponding event handler event types) that must be supported,
+ as event handler IDL attributes, by all objects implementing the
+ NavigationHistoryEntry
interface:
Event handler + | Event handler event type + |
---|---|
ondispose
+ | dispose
+ |
entries = navigation.entries()
Returns an array of NavigationHistoryEntry
instances represent the current navigation history entry list, i.e., all session history entries for this navigable that are same origin and contiguous to the current session history entry.
navigation.currentEntry
Returns the NavigationHistoryEntry
corresponding to the current session history entry.
navigation.updateCurrentEntry({ state }
Updates the navigation API state of the current session history entry, without performing a navigation like navigation.reload()
would do.
This method is best used to capture updates to the page that have already happened, and need to be reflected into the navigation API state. For cases where the state update is meant to drive a page update, instead use navigation.navigate()
or navigation.reload()
, which will trigger a navigate
event.
navigation.canGoBack
Returns true if the current current session history entry (i.e., currentEntry
) is not the first one in the navigation history entry list (i.e., in entries()
). This means that there is a previous session history entry for this navigable, and its document state's origin is same origin with the current Document
's origin.
navigation.canGoForward
Returns true if the current current session history entry (i.e., currentEntry
) is not the last one in the navigation history entry list (i.e., in entries()
). This means that there is a next session history entry for this navigable, and its document state's origin is same origin with the current Document
's origin.
The entries()
method steps are:
If this has entries and events disabled, then return the empty list.
Return this's entry list.
+ +Recall that because of Web IDL's sequence type conversion rules, this will create a new JavaScript array object on each call. That is, navigation.entries() !== navigation.entries()
.
The currentEntry
getter steps are to return the current entry of this.
The updateCurrentEntry(options)
method steps are:
Let current be the current entry of this.
If current is null, then throw an "InvalidStateError
" DOMException
.
Let serializedState be StructuredSerializeForStorage(options["state
"]), rethrowing any excpetions.
Set current's session history entry's navigation API state to serializedState.
Fire an event named currententrychange
at this using NavigationCurrentEntryChangeEvent
, with its navigationType
attribute initialized to null and its from
initialized to current.
The canGoBack
getter steps are:
If this has entries and events disabled, then return false.
Assert: this's current entry index is not −1.
If this's current entry index is 0, then return false.
Return true.
The canGoForward
getter steps are:
If this has entries and events disabled, then return false.
Assert: this's current entry index is not −1.
If this's current entry index is equal to this's entry list's size, then return false.
Return true.
{ committed, finished } = navigation.navigate(url)
{ committed, finished } = navigation.navigate(url, options)
Navigates the current page to the given url. options can contain the following values:
+ +history
can be set to "replace
" to replace the current session history entry, instead of pushing a new one.
info
can be set to any value; it will populate the info
property of the corresponding NavigateEvent
.
state
can be set to any serializable value; it will populate the state retrieved by navigation.currentEntry.getState()
once the navigation completes, for same-document navigations., (It will be ignored for navigations that end up cross-document.)
By default this will perform a full navigation (i.e., a cross-document navigation, unless the given URL differs only in a fragment from the current one). The navigateEvent.intercept()
method can be used to convert it into a same-document navigation.
The returned promises will behave as follows:
+ +For navigations that get aborted, both promises will reject with an "AbortError
" DOMException
.
For same-document navigations created by using the navigateEvent.intercept()
method, committed
will fulfill immediately, and finished
will fulfill or reject according to any promsies returned by handlers passed to intercept()
.
For other same-document navigations (e.g., non-intercepted fragment navigations), both promises will fulfill immediately.
For cross-document navigations, or navigations that result in 204 or 205 statuses or `Content-Disposition: attachment
` header fields from the server (and thus do not actually navigate), both promises will never settle.
In all cases ,when the returned promises fulfill, it will be with the NavigationHistoryEntry
that was navigated to.
{ committed, finished } = navigation.reload(options)
Reloads the current page. options can contain info
and state
, which behave as described above.
The default behavior of performing a from-network-or-cache reload of the current page can be overriden by the using the navigateEvent.intercept()
method. Doing so will mean this call only updates state or passes along the appropriate info
, plus performing whater actions the navigate
event handlers see fit to carry out.
The returned promises will behave as follows:
+ +If the reload is intercepted by using the navigateEvent.intercept()
method, committed
will fulfill immediately, and finished
will fulfill or reject according to any promsies returned by handlers passed to intercept()
.
Otherwise, both promises will never settle.
{ committed, finished } = navigation.traverseTo(key)
{ committed, finished } = navigation.traverseTo(key, { info })
Traverses to the closest session history entry that matches the NavigationHistoryEntry
with the given key. info
can be set to any value; it will populate the info
property of the corresponding NavigateEvent
.
If a traversal to that session history entry is already in progress, then this will return the promises for that original traversal, and info
will be ignored.
The returned promises will behave as follows:
+ +If there is no NavigationHistoryEntry
in navigation.entries()
whose key
matches key, both promises will reject with an "InvalidStateError
" DOMException
.
For same-document traversals intercepted by the navigateEvent.intercept()
method, committed
will fulfill as soon as the traversal is processed and navigation.currentEntry
is updated, and finished
will fulfill or reject according to any promsies returned by the handlers passed to intercept()
.
For non-intercepted same-document travesals, both promises will fulfill as soon as the traversal is processed and navigation.currentEntry
is updated.
For cross-document traversals, including attempted cross-document traversals that end up resulting in a 204 or 205 statuses or `Content-Disposition: attachment
` header fields from the server (and thus do not actually traverse), both promises will never settle.
{ committed, finished } = navigation.back(key)
{ committed, finished } = navigation.back(key, { info })
Traverses to the closest previous session history entry which results in this navigable traversing, i.e. which corresponds to a different NavigationHistoryEntry
and thus will cause navigation.currentEntry
to change. info
can be set to any value; it will populate the info
property of the corresponding NavigateEvent
.
If a traversal to that session history entry is already in progress, then this will return the promises for that original traversal, and info
will be ignored.
The returned promises behave equivalently to those returned by traverseTo()
.
{ committed, finished } = navigation.forward(key)
{ committed, finished } = navigation.forward(key, { info })
Traverses to the closest forward session history entry which results in this navigable traversing, i.e. which corresponds to a different NavigationHistoryEntry
and thus will cause navigation.currentEntry
to change. info
can be set to any value; it will populate the info
property of the corresponding NavigateEvent
.
If a traversal to that session history entry is already in progress, then this will return the promises for that original traversal, and info
will be ignored.
The returned promises behave equivalently to those returned by traverseTo()
.
The navigate(options)
method steps are:
Parse 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 resulting URL record.
Let document be this's relevant global object's associated Document
.
If options["history
"] is "push
", and any of the following are true:
document's is initial about:blank
is true;
document is not completely loaded;
urlRecord equals document's URL; or
urlRecord's scheme is "javascript
"
then return an early error result for a "NotSupportedError
" DOMException
.
These are the conditions under which a "push
" navigation will be converted into a "replace
" navigation by the navigate algorithm or by the below step. If the developer explicitly requested a push, we fail to let them know it won't happen.
In the future, we could consider loosening some of these conditions.
+Let state be options["state
"], if it exists; otherwise, undefined.
Let serializedState be StructuredSerializeForStorage(state). If this throws an exception, then return an early error result for that exception.
+ +It is importantly to perform this step early, since serialization can invoke web developer code, which in turn might change various things we check in later steps.
+If document is not fully active, then return an early error result for an "InvalidStateError
" DOMException
.
If document's unload counter is greater than 0, then return an early error result for an "InvalidStateError
" DOMException
.
Let info be options["info
"], if it exists; otherwise, undefined.
Let historyHandling be "replace
" if options["history
"] is "replace
" or if document is not completely loaded; otherwise, "push
".
Let apiMethodTracker be the result of setting the upcoming non-traverse API method tracker for this given info and serializedState.
Navigate document's node navigable to urlRecord using document, with historyHandling set to historyHandling and navigationAPIState set to serializedState.
+ +Unlike location.assign()
and friends, which are exposed across origin-domain boundaries, navigation.navigate()
can only be accessed by code with direct synchronous access to the window.navigation
property. Thus, we avoid the complications about attributing the source document of the navigation, and we don't need to deal with the allowed by sandboxing to navigate check and its acccompanying exceptionsEnabled flag. We just treat all navigations as if they come from the Document
corresponding to this Navigation
object itself (i.e., document).
If this's upcoming non-traverse API method tracker is apiMethodTracker, then:
+ +This means the navigate algorithm bailed out before ever getting to the inner navigate
event firing algorithm which would promote that upcoming API method tracker to ongoing.
Set this's upcoming non-traverse API method tracker to null.
Return an early error result for an "AbortError
" DOMException
.
Return a navigation API method tracker-derived result for apiMethodTracker.
The reload(options)
method steps are:
Let document be this's relevant global object's associated Document
.
Let serializedState be StructuredSerializeForStorage(undefined).
If options["state
"] exists, then set serializedState to StructuredSerializeForStorage(options["state
"]). If this throws an exception, then return an early error result for that exception.
It is importantly to perform this step early, since serialization can invoke web developer code, which in turn might change various things we check in later steps.
+Otherwise:
+ +Let current be the current entry of this.
If current is not null, then set serializedState to current's session history entry's navigation API state.
If document is not fully active, then return an early error result for an "InvalidStateError
" DOMException
.
If document's unload counter is greater than 0, then return an early error result for an "InvalidStateError
" DOMException
.
Let info be options["info
"], if it exists; otherwise, undefined.
Let apiMethodTracker be the result of setting the upcoming non-traverse API method tracker for this given info and serializedState.
Reload document's node navigable with navigationAPIState set to serializedState.
Return a navigation API method tracker-derived result for apiMethodTracker.
The traverseTo(key, options)
method steps are:
If this's current entry index is −1, then return an early error result for an "InvalidStateError
" DOMException
.
If this's entry list does not contain a NavigationHistoryEntry
whose session history entry's navigation API key equals key, then return an early error result for an "InvalidStateError
" DOMException
.
Return the result of performing a navigation API traversal given this, key, and options.
The back(options)
method steps are:
If this's current entry index is −1 or 0, then return an early error result for an "InvalidStateError
" DOMException
.
Let key be this's entry list[this's current entry index − 1]'s session history entry's navigation API key.
Return the result of performing a navigation API traversal given this, key, and options.
The forward(options)
method steps are:
If this's current entry index is −1 or is equal to this's entry list's size − 1, then return an early error result for an "InvalidStateError
" DOMException
.
Let key be this's entry list[this's current entry index + 1]'s session history entry's navigation API key.
Return the result of performing a navigation API traversal given this, key, and options.
To perform a navigation API traversal given a Navigation
navigation, a string key, and a NavigationOptions
options:
Let document be navigation's relevant global object's associated Document
.
If document is not fully active, then return an early error result for an "InvalidStateError
" DOMException
.
If document's unload counter is greater than 0, then return an early error result for an "InvalidStateError
" DOMException
.
Let current be the current entry of navigation.
If key equals current's session history entry's navigation API key, then return «[ "committed
" → a promise resolved with current, "finished
" → a promise resolved with current ]».
If navigation's upcoming traverse API method trackers[key] exists, then return a navigation API method tracker-derived result for navigation's upcoming traverse API method trackers[key].
Let info be options["info
"], if it exists; otherwise, undefined.
Let apiMethodTracker be the result of adding an upcoming traverse API method tracker for navigation given key and info.
Let navigable be document's node navigable.
Let traversable be navigable's traversable navigable.
Let sourceSnapshotParams be the result of snapshotting source snapshot params given document.
Append the following session history traversal steps to traversable:
+ +Let navigableSHEs be the result of getting session history entries given navigable.
Let targetSHE be the session history entry in navigableSHEs whose navigation API key is key. If no such entry exists, then:
+ +Queue a global task on the navigation and traversal task source given navigation's relevant global object to reject the finished promise for apiMethodTracker with an "InvalidStateError
" DOMException
.
Abort these steps.
This path is taken if navigation's entry list was outdated compared to navigableSHEs, which can occur for brief periods while all the relevant threads and processes are being synchronized in reaction to a history change.
+If targetSHE is navigable's active session history entry, then abort these steps.
+ +This can occur if a previously queued traversal already took us to this session history entry. In that case the previous traversal will have dealt with apiMethodTracker already.
+Let result be the result of applying the history step given by targetSHE's step to traversable, with checkForUserCancelation set to true, sourceSnapshotParams set to sourceSnapshotParams, and initiatorToCheck set to navigable. TODO actually change apply the history step to have a useful return value.
If result is "canceled
", then queue a global task on the navigation and traversal task source given navigation's relevant global object to finalize with an aborted navigation error given navigation and apiMethodTracker.
If result is "initiator-disallowed
", then queue a global task on the navigation and traversal task source given navigation's relevant global object to finalize with an aborted navigation error given navigation, apiMethodTracker, and a new "SecurityError
" DOMException
created in navigation's relevant realm.
Return a navigation API method tracker-derived result for apiMethodTracker.
An early error result for an exception e is a NavigationResult
dictionary instance given by «[ "committed
" → a promise rejected with e, "finished
" → a promise rejected with e ]».
A navigation API method tracker-derived result for a navigation API method tracker is a NavigationResult
dictionary instance given by «[ apiMethodTracker's committed promise, "finished
" → apiMethodTracker's finished promise ]».
During any given navigation (in the broad sense of the word), the Navigation
object needs to keep track of the following:
State + | Duration + | Explanation + |
---|---|---|
The NavigateEvent
+ | For the duration of event firing + | So that if the navigation is canceled while the event is firing, we can cancel the event + |
The event's signal
+ | Until all promises returned from handlers passed to intercept() have settled
+ | So that if the navigation is canceled, we can signal abort + |
Whether a new element was focused + | Until all promises returned from handlers passed to intercept() have settled
+ | So that if one was, focus is not reset + |
The NavigationHistoryEntry being navigated to
+ | From when it is determined, until all promises returned from handlers passed to intercept() have settled
+ | So that we know what to resolve any committed and finished promises with
+ |
Any finished promise that was returned
+ | Until all promises returned from handlers passed to intercept() have settled
+ | So that we can resolve or reject it appropriately + |
State + | Duration + | Explanation + |
---|---|---|
Any state
+ | For the duration of event firing + | So that we can update the current entry's navigation API state if the event finishes firing without being canceled + |
State + | Duration + | Explanation + |
---|---|---|
Any info
+ | Until the task is queued to fire the navigate event
+ | So that we can use it to fire the navigate after the trip through the session history traversal queue.
+ |
Any committed promise that was returned
+ | Until the session history is updated (inside that same task) + | So that we can resolve or reject it appropriately + |
Whether intercept() was called
+ | Until the session history is updated (inside that same task) + | So that we can suppress the normal scroll restoration logic in favor of the behavior given by the scroll option
+ |
We also cannot assume there is only a single navigation requested at any given time, due to web developer code such as:
+ +const p1 = navigation.navigate(url1).finished;
+const p2 = navigation.navigate(url2).finished;
+
+ That is, in this scenario, we need to ensure that while navigating to url2
, we still have the promise p1
around so that we can reject it. We can't just get rid of any ongoing navigation promises the moment the second call to navigate()
happens.
We end up accomplishing all this by associating the following with each Navigation
:
Ongoing navigate
event, a NavigateEvent
or null, initially null.
Ongoing navigation signal, an AbortSignal
or null, initially null.
Focus changed during ongoing navigation, a boolean, initially false.
Suppress normal scroll restoration during ongoing navigation, a boolean, initially false.
Ongoing API method tracker, a navigation API method tracker or null, initially null.
Upcoming non-traverse API method tracker, a navigation API method tracker or null, initially null.
Upcoming traverse API method trackers, a map from strings to navigation API method trackers, initially empty.
The state here that is not stored in navigation API method trackers is state which needs to be tracked even for navigations that are not via navigation API methods.
+ +A navigation API method tracker is a struct with the following items:
+ +A navigation object, a Navigation
A key, a string or null
An info, a JavaScript value
A serialized state, a serialized state or null
A committed-to entry, a NavigationHistoryEntry
or null
A committed promise, a promise
A finished promise, a promise
All this state is then managed via the following algorithms.
+ +To set the upcoming non-traverse API method tracker given a Navigation
navigation, a JavaScript value info, and a serialized state-or-null serializedState:
Let committedPromise and finishedPromise be new promises created in navigation's relevant realm.
Mark as handled finishedPromise.
+ + +Let apiMethodTracker be a new navigation API method tracker with:
+ +Assert: navigation's upcoming non-traverse API method tracker is null.
Set navigation's upcoming non-traverse API method tracker to apiMethodTracker.
Return apiMethodTracker.
To add an upcoming traverse API method tracker given a Navigation
navigation, a string destinationKey, and a JavaScript value info:
Let committedPromise and finishedPromise be new promises created in navigation's relevant realm.
Mark as handled finishedPromise.
+ +See the previous discussion about why this is done.
+Let apiMethodTracker be a new navigation API method tracker with:
+ +Set navigation's upcoming traverse API method trackers[key] to apiMethodTracker.
Return apiMethodTracker.
To promote an upcoming API method tracker to ongoing given a Navigation
navigation and a string-or-null destinationKey:
Assert: navigation's ongoing API method tracker is null.
If destinationKey is not null, then:
+ +Assert: navigation's upcoming non-traverse API method tracker is null.
If navigation's upcoming traverse API method trackers[destinationKey] exists, then:
+ +Set navigation's ongoing API method tracker to navigation's upcoming traverse API method trackers[destinationKey].
Remove navigation's upcoming traverse API method trackers[destinationKey].
Otherwise:
+ +Set navigation's ongoing API method tracker to navigation's upcoming non-traverse API method tracker.
Set navigation's upcoming non-traverse API method tracker to null.
To clean up a navigation API method tracker apiMethodTracker:
+ +Let navigation be apiMethodTracker's navigation object.
If navigation's ongoing API method tracker is apiMethodTracker, then set navigation's ongoing API method tracker to null.
Otherwise:
+ +Let key be apiMethodTracker's key.
Assert: key is not null.
Assert: navigation's upcoming traverse API method trackers[key] exists.
Remove navigation's upcoming traverse API method trackers[key].
To notify about the committed-to entry given a navigation API method tracker apiMethodTracker and a NavigationHistoryEntry
nhe:
Set apiMethodTracker's committed-to entry to nhe.
If apiMethodTracker's serialized state is not null, then set nhe's session history entry's navigation API state to apiMethodTracker's serialized state.
+ +If it's null, then we're traversing to nhe via navigation.traverseTo()
, which does not allow changing the state.
At this point, apiMethodTracker's serialized state is no longer needed. Implementations might want to clear it out to avoid keeping it alive for the lifetime of the navigation API method tracker.
+Resolve apiMethodTracker's committed promise with nhe.
+ +At this point, apiMethodTracker's committed promise is only needed in cases where it has not yet been returned to author code. Implementations might want to clear it out to avoid keeping it alive for the lifetime of the navigation API method tracker.
+To resolve the finished promise for a navigation API method tracker apiMethodTracker:
+ +If apiMethodTracker's finished promise is null, then return.
Resolve apiMethodTracker's finished promise with its committed-to entry.
Clean up apiMethodTracker.
To reject the finished promise for a navigation API method tracker apiMethodTracker with a JavaScript value exception:
+ +If apiMethodTracker's finished promise is null, then return.
If apiMethodTracker's committed promise is not null, then reject apiMethodTracker's committed promise with exception.
Reject apiMethodTracker's finished promise with exception.
Clean up apiMethodTracker.
To finalize with an aborted navigation error given a Navigation
navigation, a navigation API method tracker or null apiMethodTracker, and an optional DOMException
error:
Set navigation's focus changed during ongoing navigation to false.
Set navigation's suppress normal scroll restoration during ongoing navigation to false.
If error was not given, then let error be a new "AbortError
" DOMException
created in navigation's relevant realm.
If navigation's ongoing navigate
event is non-null, then:
Set navigation's ongoing navigate
event's canceled flag to true.
Set navigation's ongoing navigate
event to null.
If navigation's ongoing navigation signal is non-null, then:
+ +Signal abort on navigation's ongoing navigation signal given error.
Set navigation's ongoing navigation signal to null.
Fire an event named navigateerror
at navigation using ErrorEvent
, with error
initialized to error, and message
, filename
, lineno
, and colno
initialized to appropriate values that can be extracted from error and the current JavaScript stack in the same underspecified way that the report the exception algorithm does.
Thus, for example, if this algorithm is reached because of a call to window.stop()
, these properties would probably end up initialized based on the line of script that called window.stop()
. But if it's because the user clicked the stop button, these properties would probably end up with default values like the empty string or 0.
If apiMethodTracker is non-null, then reject the finished promise for apiMethodTracker with error.
If navigation's transition is not null, then:
+ +Reject navigation's transition's finished promise with error.
Set navigation's transition to null.
To inform the navigation API about aborting navigation in a navigable navigable:
+ +If this algorithm is running on navigable's active window's relevant agent's event loop, then continue on to the following steps. Otherwise, queue a global task on the navigation and traversal task source given navigable's active window to run the following steps.
Let navigation be navigable's active window's navigation API.
If navigation's ongoing navigation signal is null, then return.
Finalize with an aborted navigation error given navigation and navigation's ongoing API method tracker.
To inform the navigation API about child navigable destruction given a navigable navigable:
+ +Inform the navigation API about aborting navigation in navigable.
Let navigation be navigable's active window's navigation API.
Let traversalAPIMethodTrackers to be clone of navigation's upcoming traverse API method trackers.
For each apiMethodTracker of traversalAPIMethodTrackers: finalize with an aborted navigation error given navigation and apiMethodTracker.
The ongoing navigation concept is most-directly exposed to web developers through the navigation.transition
property, which is an instance of the NavigationTransition
interface:
[Exposed=Window]
+interface NavigationTransition {
+ readonly attribute NavigationType navigationType;
+ readonly attribute NavigationHistoryEntry from;
+ readonly attribute Promise<undefined> finished;
+};
+
+ navigation.transition
A NavigationTransition
representing any ongoing navigation that hasn't yet reached the navigatesuccess
or navigateerror
stage, if one exists; or null, if there is no such transition ongoing.
Since navigation.currentEntry
(and other properties like location.href
) are updated immediately upon navigation, this navigation.transition
property is useful for determining when such navigations are not yet fully settled, according to any handlers passed to navigateEvent.intercept()
.
navigation.transition.navigationType
One of "push
", "replace
", "reload
", or "traverse
", indicating what type of navigation this transition is for.
navigation.transition.from
The NavigationHistoryEntry
from which the transition is coming. This can be useful to compare against navigation.currentEntry
.
navigation.transition.finished
A promise which fulfills at the same time as the navigatesuccess
fires, or rejects at the same time the navigateerror
event fires.
Each Navigation
has a transition, which is a NavigationTransition
or null, initially null.
The transition
getter steps are to return this's transition.
Each NavigationTransition
has an associated navigation type, which is a NavigationType
.
Each NavigationTransition
has an associated from entry, which is a NavigationHistoryEntry
.
Each NavigationTransition
has an associated finished promise, which is a promise.
The navigationType
getter steps are to return this's navigation type.
The from
getter steps are to return this's from entry.
The finished
getter steps are to return this's finished promise.
navigate
eventA major feature of the navigation API is the navigate
event. This event is fired on any navigation (in the broad sense of the word), allowing web developers to monitor such outgoing navigations. In many cases, the event is cancelable
, which allows preventing the navigation from happening. And in others, the navigation can be intercepted and replaced with a same-document navigation by using the intercept()
method of the NavigateEvent
class.
NavigateEvent
interface[Exposed=Window]
+interface NavigateEvent : Event {
+ constructor(DOMString type, NavigateEventInit eventInitDict);
+
+ readonly attribute NavigationType navigationType;
+ readonly attribute NavigationDestination destination;
+ readonly attribute boolean canIntercept;
+ readonly attribute boolean userInitiated;
+ readonly attribute boolean hashChange;
+ readonly attribute AbortSignal signal;
+ readonly attribute FormData
? formData;
+ readonly attribute DOMString? downloadRequest;
+ readonly attribute any info;
+
+ undefined intercept(optional NavigationInterceptOptions options = {});
+ undefined scroll();
+};
+
+dictionary NavigateEventInit : EventInit {
+ NavigationType navigationType = "push";
+ required NavigationDestination destination;
+ boolean canIntercept = false;
+ boolean userInitiated = false;
+ boolean hashChange = false;
+ required AbortSignal signal;
+ FormData? formData = null;
+ DOMString? downloadRequest = null;
+ any info;
+};
+
+dictionary NavigationInterceptOptions {
+ NavigationInterceptHandler handler;
+ NavigationFocusReset focusReset;
+ NavigationScrollBehavior scroll;
+};
+
+enum NavigationFocusReset {
+ "after-transition",
+ "manual"
+};
+
+enum NavigationScrollBehavior {
+ "after-transition",
+ "manual"
+};
+
+callback NavigationInterceptHandler = Promise<undefined> ();
+
+ event.navigationType
One of "push
", "replace
", "reload
", or "traverse
", indicating what type of navigation this is.
event.destination
A NavigationDestination
representing the destination of the navigation.
event.canIntercept
True if intercept()
can be called to intercept this navigation and convert it into a same-document navigation, replacing its usual behavior; false otherwise.
Generally speaking, this will be true whenever the current Document
can have its URL rewritten to the destination URL, except for in the case of cross-document "traverse
" navigations, where it will always be false.
event.userInitiated
True if this navigation was due to a user clicking on an a
element, submitting a form
element, or using the browser UI to navigate; false otherwise.
event.hashChange
True for a fragment navigation; false otherwise.
event.signal
An AbortSignal
which will become aborted if the navigation gets canceled, e.g., by the user pressing their browser's "Stop" button, or by another navigation interrupting this one.
The expected pattern is for developers to pass this along to any async operations, such as fetch()
, which they perform as part of handling this navigation.
event.formData
The FormData
representing the submitted form entries for this navigation, if this navigation is a "push
" or "replace
" navigation representing a POST form submission; null otherwise.
(Notably, this will be null even for "reload
" or "traverse
" navigations that are revisiting a session history entry that was originally created from a form submission.)
event.downloadRequest
Represents whether or not this navigation was requested to be a download, by using an a
or area
element's download
attribute:
If a download was not requested, then this property is null.
If a download was requested, returns the filename that was supplied as the download
attribute's value. (This could be the empty string.)
Note that a download being requested does not always mean that a download will happen: for example, a download might be blocked by browser security policies, or end up being treated as a "push
" navigation for unspecified reasons.
Similarly, a navigation might end up being a download even if it was not requested to be one, due to the destination server responding with a `Content-Disposition: attachment
` header.
Finally, note that the navigate
event will not fire at all for downloads initiated using browser UI affordances, e.g., those created by right-clicking and choosing to save the target of a link.
event.info
An arbitrary JavaScript value passed via one of the navigation API methods which initiated this navigation, or undefined if the navigation was initiated by the user or by a different API.
event.intercept({ handler, focusReset, scroll })
Intercepts this navigation, preventing its normal handling and instead converting it into a same-document navigation of the same type to the destination URL.
+ +The handler
option can be a function that returns a promise. The handler function will run after the navigate
event has finished firing, and the navigation.currentEntry
property has been synchronously updated. This returned promise is used to signal the duration, and success or failure, of the navigation. After it settles, the browser signals to the user (e.g., via a loading spinner UI, or assistive technology) that the navigation is finished. Additionally, it fires navigatesuccess
or navigateerror
events as appropriate, which other parts of the web application can respond to.
By default, using this method will cause focus to reset when any handlers' returned promises settle. Focus will be reset to the first element with the autofocus
attribute set, or the body element if the attribute isn't present. The focusReset
option can be set to "manual
" to avoid this behavior.
By default, using this method will delay the browser's scroll restoration logic for "traverse
" or "reload
" navigations, or its scroll-reset/scroll-to-a-fragment logic for "push
" or "replace
" navigations, until any handlers' returned promises settle. The scroll
option can be set to "manual
" to turn off any browser-driven scroll behavior entirely for this navigation, or scroll()
can be called before the promise settles to trigger this behavior early.
This method will throw a "SecurityError
" DOMException
if canIntercept
is false, or if isTrusted
is false. It will throw an "InvalidStateError
" DOMException
if not called synchronously, during event dispatch.
event.scroll()
For "traverse
" or "reload
" navigations, restores the scroll position using the browser's usual scroll restoration logic.
For "push
" or "replace
" navigations, either resets the scroll position to the top of the document or scrolls to the fragment specified by destination.url
if there is one.
If called more than once, or called after automatic post-transition scroll processing has happened due to the scroll
option bieng left as "after-transition
", this method will throw an "InvalidStateError
" DOMException
.
Each NavigateEvent
has a classic history API state, a serialized state or null. It is only used in some cases where the event's navigationType
is "push
" or "replace
", and is set appropriately when the event is fired.
Each NavigateEvent
has a focus reset behavior, a NavigationFocusReset
-or-null, initially null.
Each NavigateEvent
has a scroll behavior, a NavigationScrollBehavior
-or-null, initially null.
Each NavigateEvent
has a did process scroll behavior, a boolean, initially false.
Each NavigateEvent
has a was intercepted, a boolean, initially false.
Each NavigateEvent
has a needs continue, a boolean, initially false.
Each NavigateEvent
has a navigation handler list, a list of NavigationInterceptHandler
callbacks, initially empty.
The navigationType
, destination
, canIntercept
, userInitiated
,
+ hashChange
, signal
, formData
, downloadRequest
, and info
attributes must
+ return the values they are initialized to.
The intercept(options)
method steps are:
If this's relevant global object's associated Document
is not fully active, then throw an "InvalidStateError
" DOMException
.
If this's isTrusted
attribute was initialized to false, then throw a "SecurityError
" DOMException
.
If this's canIntercept
attribute was initialized to false, then throw a "SecurityError
" DOMException
.
If this's dispatch flag is unset, then throw an "InvalidStateError
" DOMException
.
If this's canceled flag is set, then throw an "InvalidStateError
" DOMException
.
If options["handler
"] exists, then append it to this's navigation handler list.
Set this's was intercepted to true.
If options["focusReset
"] exists, then:
If this's focus reset behavior is not null, and it is not equal to options["focusReset
"], then the user agent may report a warning to the console indicating that the focusReset
option for a previous call to intercept()
was overridden by this new value, and the previous value will be ignored.
Set this's focus reset behavior to options["focusReset
"].
If options["scroll
"] exists, then:
If this's scroll behavior is not null, and it is not equal to options["scroll
"], then the user agent may report a warning to the console indicating that the scroll
option for a previous call to intercept()
was overridden by this new value, and the previous value will be ignored.
Set this's scroll behavior to options["scroll
"].
The scroll()
method steps are:
If this's did process scroll behavior is true, then throw an "InvalidStateError
" DOMException
.
If this's was intercepted is false, then throw an "InvalidStateError
" DOMException
.
If this's relevant global object's associated Document
is not fully active, then throw an "InvalidStateError
" DOMException
.
Definitely process scroll behavior given this.
NavigationDestination
interface[Exposed=Window]
+interface NavigationDestination {
+ readonly attribute USVString url;
+ readonly attribute DOMString? key;
+ readonly attribute DOMString? id;
+ readonly attribute long long index;
+ readonly attribute boolean sameDocument;
+
+ any getState();
+};
+
+ event.destination.url
The URL being navigated to.
event.destination.key
The value of the key
property of the destination NavigationHistoryEntry
, if this is a "traverse
" navigation, or null otherwise.
event.destination.id
The value of the id
property of the destination NavigationHistoryEntry
, if this is a "traverse
" navigation, or null otherwise.
event.destination.index
The value of the index
property of the destination NavigationHistoryEntry
, if this is a "traverse
" navigation, or −1 otherwise.
event.destination.sameDocument
Indicates whether or not this navigation is to the same Document
as the current one, or not. This will be true, for example, in the case of fragment navigations or history.pushState()
navigations.
Note that this property indicates the original nature of the navigation. If a cross-document navigation is converted into a same-document navigation using navigateEvent.intercept()
, that will not change the value of this property.
event.destination.getState()
For "traverse
" navigations, returns the deserialization of the state stored in the destination session history entry.
For "push
" or "replace
" navigations, returns the deserialization of the state passed to navigation.navigate()
, if the navigation was initiated by that method, or undefined it if it wasn't.
For "reload
" navigations, returns the deserialization of the state passed to navigation.reload()
, if the reload was initiated by that method, or undefined it if it wasn't.
Each NavigationDestination
has a URL, which is a URL.
Each NavigationDestination
has a key, which is a string or null.
Each NavigationDestination
has an ID, which is a string or null.
Each NavigationDestination
has an index, which is an integer.
Each NavigationDestination
has a state, which is a serialized state.
Each NavigationDestination
has an is same document, which is a boolean.
The url
getter steps are to return this's URL, serialized.
The key
getter steps are to return this's key.
The id
getter steps are to return this's ID.
The index
getter steps are to return this's index.
The sameDocument
getter steps are to return this's is same document.
The getState()
method steps are to return StructuredDeserialize(this's state).
Other parts of the standard fire the navigate
event, through a series of wrapper algorithms given in this section.
To fire a traverse navigate
event at a Navigation
navigation given a session history entry destinationSHE and an optional user navigation involvement userInvolvement (default "none
"):
Let event be the result of creating an event given NavigateEvent
, in navigation's relevant realm.
Set event's classic history API state to null.
Let destination be a new NavigationDestination
created in navigation's relevant realm.
Set destination's URL to destinationSHE's URL.
If destinationSHE's document state's origin is same origin with navigation's relevant settings object's origin, then:
+ +Set destination's key to destinationSHE's navigation API key.
Set destination's id to destinationSHE's navigation API ID.
Set destination's index to the result of getting the navigation API entry index of destinationSHE within navigation.
Set destination's state to destinationSHE's navigation API state.
Otherwise,
+ +Set destination's key to null.
Set destination's id to null.
Set destination's index to −1.
Set destination's state to StructuredSerializeForStorage(null).
Set destination's is same document to true if destinationSHE's document is equal to navigation's relevant global object's associated Document
; otherwise false.
Return the result of performing the inner navigate
event firing algorithm given navigation, "traverse
", event, destination, userInvolvement, null, and null.
To fire a push/replace/reload navigate
event at a Navigation
navigation given a NavigationType
navigationType, a URL destinationURL, a boolean isSameDocument, an optional user navigation involvement userInvolvement (default "none
"), an optional entry list-or-null formDataEntryList (default null), an optional serialized state navigationAPIState (default StructuredSerializeForStorage(null)), and an optional serialized state-or-null classicHistoryAPIState (default null):
Let event be the result of creating an event given NavigateEvent
, in navigation's relevant realm.
Set event's classic history API state to classicHistoryAPIState.
Let destination be a new NavigationDestination
created in navigation's relevant realm.
Set destination's URL to destinationURL.
Set destination's key to null.
Set destination's id to null.
Set destination's index to −1.
Set destination's state to navigationAPIState.
Set destination's is same document to isSameDocument.
Return the result of performing the inner navigate
event firing algorithm given navigation, navigationType, event, destination, userInvolvement, formDataEntryList, and null.
To fire a download request navigate
event at a Navigation
navigation given a URL destinationURL, a user navigation involvement userInvolvement, and a string filename:
Let event be the result of creating an event given NavigateEvent
, in navigation's relevant realm.
Set event's classic history API state to null.
Let destination be a new NavigationDestination
created in navigation's relevant realm.
Set destination's URL to destinationURL.
Set destination's key to null.
Set destination's id to null.
Set destination's index to −1.
Set destination's state to StructuredSerializeForStorage(null).
Set destination's is same document to false.
Return the result of performing the inner navigate
event firing algorithm given navigation, "push
", event, destination, userInvolvement, null, and filename.
The inner navigate
event firing algorithm consists of the following steps, given a Navigation
navigation, a NavigationType
navigationType, a NavigateEvent
event, a NavigationDestination
destination, a user navigation involvement userInvolvement, an entry list-or-null formDataEntryList, and a string-or-null downloadRequestFilename:
Promote an upcoming API method tracker to ongoing given navigation and destination's key.
Let apiMethodTracker be navigation's ongoing API method tracker.
If navigation has entries and events disabled, then:
+ +If apiMethodTracker is not null, then clean up apiMethodTracker.
+ +In this case the committed promise and finished promise will never fulfill, since we never create a NavigationHistoryEntry
object for such Document
s, and so we have nothing to resolve them with.
Return true.
Let navigable be navigation's relevant global object's navigable.
Let document be navigation's relevant global object's associated Document
.
If document can have its URL rewritten to destination's URL, and either destination's is same document is true or navigationType is not "traverse
", then initialize event's canIntercept
to true. Otherwise, initialize it to false.
Let traverseCanBeCanceled be true if userInvolvement is not "browser UI
", or if navigation's relevant global object has transient activation; otherwise, false.
The user activation check here is expected to get slightly more lenient in the future; see WICG/navigation-api#32.
+If any of the following are true:
+ +navigationType is not "traverse
"; or
navigable is a top-level traversable and traverseCanBeCanceled is true
the initialize event's cancelable
to true. Otherwise, initialize it to false.
Initialize event's type
to "navigate
".
Initialize event's navigationType
to navigationType.
Initialize event's destination
to destination.
Initialize event's downloadRequest
to downloadRequestFilename.
If apiMethodTracker is not null, then initialize event's info
to apiMethodTracker's info. Otherwise, initialize it to undefined.
At this point apiMethodTracker's info is no longer needed and can be nulled out instead of keeping it alive for the lifetime of the navigation API method tracker.
+Initialize event's signal
to a new AbortSignal
created in navigation's relevant realm.
Let currentURL be document's URL.
If all of the following are true:
+ +destination's is same document is true;
destination's URL equals currentURL with exclude fragments set to true; and
destination's URL's fragment is not identical to currentURL's fragment
then initialize event's hashChange
to true. Otherwise, initialize it to false.
If userInvolvement is not "none
", then initialize event's userInitiated
to true. Otherwise, initialize it to false.
If formDataEntryList is not null, then initialize event's formData
to a new FormData
created in navigation's relevant realm, associated to formDataEntryList. Otherwise, initialize it to null.
Assert: navigation's ongoing navigate
event is null.
Set navigation's ongoing navigate
event to event.
Assert: navigation's ongoing navigation signal is null.
Set navigation's ongoing navigation signal to event's signal
.
Set navigation's focus changed during ongoing navigation to false.
Set navigation's suppress normal scroll restoration during ongoing navigation to false.
Let dispatchResult be the result of dispatching event at navigation.
If dispatchResult is false:
+ +If navigationType is not "traverse
" and event's signal
is not aborted, then finalize with an aborted navigation error given navigation and apiMethodTracker.
If navigationType is "traverse
", then we will instead finalize with an aborted navigation error in perform a navigation API traversal. TODO this doesn't seem right; what about history.back()?? Probably the finalize needs to move to "apply the history step"?
Return false.
If destination's is same document is true and navigationType is "traverse
":
Set event's needs continue to true.
Return true.
Return the result of reacting to the navigate
event result given navigation and event.
To react to the navigate
event result, given a Navigation
navigation and a NavigateEvent
event:
Let navigationType be event's navigationType
.
Let apiMethodTracker be navigation's ongoing API method tracker.
Let endResultIsSameDocument be true if event's was intercepted is true or event's destination
's is same document is true.
Prepare to run script given navigation's relevant settings object.
+ + +If event's was intercepted is true:
+ +Let fromNHE be the current entry of navigation.
Assert: fromNHE is not null.
Set navigation's transition to a new NavigationTransition
created in navigation's relevant realm, whose navigation type is navigationType, from entry is fromNHE, and whose finished promise is a new promise created in navigation's relevant realm.
Mark as handled navigation's transition's finished promise.
+ +See the discussion about other finished promises to understand why this is done.
+If navigationType is "traverse
", then set navigation's suppress normal scroll restoration during ongoing navigation to true.
If event's scroll behavior was set to "after-transition
", then we will potentially process scroll behavior below. Otherwise, there will be no scroll restoration. That is, no navigation which is intercepted by intercept()
goes through the normal scroll restoration process; scroll restoration for such navigations is either done manually, by the web developer, or is done after the transition.
If navigationType is "push
" or "replace
", then run the URL and history update steps given document and event's destination
's URL, with serialiedData set to event's classic history API state and historyHandling set to navigationType.
If navigationType is "reload
", then we are converting a reload into a "same-document reload", for which the URL and history update steps are not appropriate. Navigation API-related stuff still happens, such as updating the active session history entry's navigation API state if this was caused by a call to navigation.reload()
, and all the ongoing navigation tracking.
If endResultIsSameDocument is true:
+ +Let promisesList be an empty list.
For each handler of event's navigation handler list:
+ +Append the result of invoking handler with an empty arguments list to promisesList.
If promisesList's size is 0, then set promisesList to « a promise resolved with undefined ».
+ +There is a subtle timing difference between how waiting for all schedules its success and failure steps when given zero promises versus ≥1 promises. For most uses of waiting for all, this does not matter. However, with this API, there are so many events and promise handlers which could fire around the same time that the difference is pretty easily observable: it can cause the event/promise handler sequence to vary. (Some of the events and promises involved include: navigatesuccess
/ navigateerror
, currententrychange
, dispose
, apiMethodTracker's promises, and the navigation.transition.finished
promise.)
+
Wait for all of promisesList, with the following success steps:
+ +If event's signal
is aborted, then abort these steps.
If event equals navigation's ongoing navigate
event, then set navigation's ongoing navigate
event to null.
Fire an event named navigatesuccess
at navigation.
If navigation's transition is not null, then resolve navigation's transition's finished promise with undefined.
Set navigation's transition to null.
If apiMethodTracker is non-null, then resolve the finished promise for apiMethodTracker.
Potentially reset the focus given event.
Potentially process scroll behavior given event.
and the following failure steps given reason rejectionReason:
+ +If event's signal
is aborted, then abort these steps.
Fire an event named navigateerror
at navigation using ErrorEvent
, with error
initialized to rejectionReason, and message
, filename
, lineno
, and colno
initialized to appropriate values that can be extracted from rejectionReason in the same underspecified way that the report the exception algorithm does.
If navigation's transition is not null, then reject navigation's transition's finished promise with rejectionReason.
Set navigation's transition to null.
If apiMethodTracker is non-null, then reject the finished promise for apiMethodTracker with rejectionReason.
Potentially reset the focus given event.
+ +Although we still potentially reset the focus for such failed transitions, we do not potentially process scroll behavior for them.
+Otherwise, if apiMethodTracker is non-null, then clean up apiMethodTracker.
Clean up after running script given navigation's relevant settings object.
+ +Per the previous note, this stops suppress any potential promise handler microtasks, causing them to run at this point or later.
+If event's was intercepted is true, then return false.
Return true.
To maybe continue the navigate
event, given a Navigation
navigation:
If navigation's ongoing navigate
event is null, or navigation's ongoing navigate
event's needs continue is false, then return.
React to the navigate
event result given navigation and navigation's ongoing navigate
event.
By calling navigateEvent.intercept()
, web developers can suppress the normal scroll and focus behavior for same-document navigations, instead invoking cross-document navigation-like behavior at a later time. The algorithms in this section are called at those appropriate later points.
To potentially reset the focus given a NavigateEvent
event:
Let navigation be event's relevant global object's navigation API.
Let focusChanged be navigation's focus changed during ongoing navigation.
Set navigation's focus changed during ongoing navigation to false.
If focusChanged is true, then return.
If event's was intercepted is false, then return.
If event's focus reset behavior is "manual
", then return.
If it was left as null, then we treat that as "after-transition
", and continue onward.
Let document be event's relevant global object's associated Document
.
Let focusTarget be the autofocus delegate for document.
If focusTarget is null, then set focusTarget to document's body element.
If focusTarget is null, then set focusTarget to document's document element.
Run the focusing steps for focusTarget, with document's viewport as the fallback target.
Move the sequential focus navigation starting point to focusTarget.
To potentially process scroll behavior given a NavigateEvent
event:
If event's was intercepted is false, then return.
If event's scroll behavior is "manual
", then return.
If it was left as null, then we treat that as "after-transition
", and continue onward.
If event's did process scroll behaviordid process scroll behavior is true, then return.
Definitely process scroll behavior given event.
To definitely process scroll behavior given a NavigateEvent
event:
Set event's did process scroll behavior to true.
If event's navigationType
was initialized to "traverse
" or "reload
", then restore scroll position data given event's relevant global object's navigable's active session history entry.
Otherwise:
+ + +The NavigateEvent
interface has its own dedicated section, due to its complexity.
NavigationCurrentEntryChangeEvent
interface[Exposed=Window]
+interface NavigationCurrentEntryChangeEvent : Event {
+ constructor(DOMString type, NavigationCurrentEntryChangeEventInit eventInitDict);
+
+ readonly attribute NavigationType? navigationType;
+ readonly attribute NavigationHistoryEntry from;
+};
+
+dictionary NavigationCurrentEntryChangeEventInit : EventInit {
+ NavigationType? navigationType = null;
+ required NavigationHistoryEntry from;
+};
+
+ event.navigationType
Returns the type of navigation which caused the current entry to change, or null if the change is due to navigation.updateCurrentEntry()
.
event.from
Returns the previous value of navigation.currentEntry
, before the current entry changed.
If navigationType
is null or "reload
", then this value will be the same as navigation.currentEntry
. In that case, the event signifies that the contents of the entry changed, even if we did not move to a new entry or replace the current one.
The navigationType
and from
attributes must return the values they were initialized to.
PopStateEvent
interfaceSet container's nested navigable to null.
Inform the navigation API about child navigable destruction given + nestedNavigable.
Destroy nestedNavigable's active document.
document state, a document state.
serialized state, which is serialized - state, initially StructuredSerializeForStorage(null).
classic history API + state, which is serialized state, initially + StructuredSerializeForStorage(null).
navigation API state, which is a + serialized state, initially + StructuredSerializeForStorage(undefined).
navigation API key, which is a string, + initially set to the result of generating a random UUID.
navigation API ID, which is a string, initially + set to the result of generating a random UUID.
scroll restoration mode, a scroll
restoration mode, initially "
standard when manipulating session history. The best way to get a sense of what they do is to
look at their call sites.
To get session history entries for a - navigable, navigable:
+To get session history entries of a + navigable navigable:
Let traversable be navigable's
Assert: this step is not reached.
To get session history + entries for the navigation API of a navigable navigable given an + integer targetStep:
+ +Let rawEntries be the result of getting session history entries + for navigable.
Let entriesForNavigationAPI be a new empty list.
Let startingIndex be the index of the session history entry in + rawEntries who has the greatest step less than or + equal to targetStep.
+ +See this example to + understand why it's the greatest step less than or equal to targetStep.
+Append rawEntries[startingIndex] + to entriesForNavigationAPI.
Let startingOrigin be rawEntries[startingIndex]'s document state's origin.
Let i be startingIndex − 1.
While i > 0:
+ +If rawEntries[i]'s document + state's origin is not same + origin with startingOrigin, then break.
Prepend rawEntries[i] to + entriesForNavigationAPI.
Set i to i − 1.
Set i to startingIndex + 1.
While i < rawEntries's size:
+ +If rawEntries[i]'s document + state's origin is not same + origin with startingOrigin, then break.
Append rawEntries[i] to + entriesForNavigationAPI.
Set i to i + 1.
Return entriesForNavigationAPI.
To clear the forward session history of a traversable navigable navigable:
@@ -89273,7 +91464,7 @@ location.href = '#foo'; data-x="dom-open">window.open() andlocation.assign()
methods can all cause navigation.
-