HTML Standard
7.4
Navigation and session
history
7.4.1
Session history
7.4.1.1
Session history entries
7.4.1.2
Document state
7.4.1.3
Centralized modifications of session history
7.4.1.4
Low-level operations on session history
7.4.2
7.4.2.1
Supporting concepts
7.4.2.2
Beginning navigation
7.4.2.3
Ending navigation
7.4.2.3.1
The usual cross-document navigation case
7.4.2.3.2
The
javascript:
URL special case
7.4.2.3.3
Fragment navigations
7.4.2.3.4
Non-fetch schemes and external software
7.4.2.4
Preventing navigation
7.4.2.5
Aborting navigation
7.4.3
Reloading and traversing
7.4.4
Non-fragment synchronous "navigations"
7.4.5
Populating a session history entry
7.4.6
Applying the history step
7.4.6.1
Updating the traversable
7.4.6.2
Updating the document
7.4.6.3
Revealing the document
7.4.6.4
Scrolling to a fragment
7.4.6.5
Persisted history entry state
7.4
Navigation and session
history
Welcome to the dragon's maw. Navigation, session history, and the traversal through that
session history are some of the most complex parts of this standard.
The basic concept may not seem so difficult:
The user is looking at a
navigable
that is presenting its
active document
. They
navigate
it to another
URL
The browser fetches the given URL from the network, using it to
populate
a new
session history entry
with a newly-
created
Document
The browser updates the
navigable
's
active session history entry
to the newly-populated
one, and thus updates the
active document
that it is showing
to the user.
At some point later, the user
presses the
browser back button
to go back to the previous
session history
entry
The browser looks at the
URL
stored in that
session
history entry
, and uses it to re-fetch and
populate
that entry's
document
The browser again updates the
navigable
's
active session history entry
You can see some of the intertwined complexity peeking through here, in how traversal can
cause a navigation (i.e., a network fetch to a stored URL), and how a navigation necessarily
needs to interface with the session history list to ensure that when it finishes the user is
looking at the right thing. But the real problems come in with the various edge cases and
interacting web platform features:
Child navigables
(e.g., those contained in
iframe
s) can also navigate and traverse, but those navigations need to be
linearized into
a single session history list
since the user only has a single back/forward interface for the entire
traversable
navigable
(e.g., browser tab).
Since the user can traverse back more than a single step in the session history (e.g., by
holding down their back button), they can end up traversing multiple
navigables
at the same time when
child navigables
are involved. This needs to be synchronized across all of
the involved navigables, which might involve multiple
event
loops
or even
agent clusters
During navigation, servers can respond with 204 or 205 status codes or with `
Content-Disposition: attachment
` headers, which cause
navigation to abort and the
navigable
to stay on its original
active document
. (This is much worse if it happens during a traversal-initiated
navigation!)
Various other HTTP headers, such as `
Location
`,
Refresh
`, `
X-Frame-Options
`, and those for Content Security Policy,
contribute to either the
fetching
process
, or the
Document
-creation
process
, or both. The `
Cross-Origin-Opener-Policy
` header even contributes
to the
browsing
context selection and creation
process!
Some navigations (namely
fragment navigations
and
single-page app navigations
) are synchronous, meaning that
JavaScript code expects to observe the navigation's results instantly. This then needs to be
synchronized with the view of the session history that all other
navigables
in the tree see, which can be subject to race conditions
and necessitate resolving conflicting views of the session history.
The platform has accumulated various exciting navigation-related features that need
special-casing, such as
javascript:
URLs,
srcdoc
iframe
s, and the
beforeunload
event.
In what follows, we have attempted to guide the reader through these complexities by
appropriately cordoning them off into labeled sections and algorithms, and giving appropriate
words of introduction where possible. Nevertheless, if you wish to truly understand navigation
and session history,
the usual advice
will be
invaluable.
7.4.1
Session history
7.4.1.1
Session history entries
session history entry
is a
struct
with the following
items
step
, a non-negative integer or "
pending
", initially "
pending
".
URL
, a
URL
document state
, a
document
state
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 "
auto
".
scroll position data
, which is scroll position
data for the
document
's
restorable scrollable
regions
persisted user state
which is
implementation-defined
, initially null
For example, some user agents might want to persist the values of form
controls.
User agents that persist the value of form controls are encouraged to also
persist their directionality (the value of the element's
dir
attribute). This prevents values from being displayed incorrectly after a history traversal
when the user had originally entered the values with an explicit, non-default
directionality.
To get a
session history entry
's
document
return its
document state
's
document
Serialized state
is a serialization (via
StructuredSerializeForStorage
) of an object representing a user interface state. We
sometimes informally refer to "state objects", which are the objects representing user interface
state supplied by the author, or alternately the objects created by deserializing (via
StructuredDeserialize
) serialized state.
Pages can
add
serialized state
to the
session history. These are then
deserialized
and
returned to the script
when the user (or script) goes back in the
history, thus enabling authors to use the "navigation" metaphor even in one-page applications.
Serialized state
is intended to be used for two main purposes: first, storing a
preparsed description of the state in the
URL
so that in the simple case an author
doesn't have to do the parsing (though one would still need the parsing for handling
URLs
passed around by users, so it's only a minor optimization). Second, so
that the author can store state that one wouldn't store in the URL because it only applies to the
current
Document
instance and it would have to be reconstructed if a new
Document
were opened.
An example of the latter would be something like keeping track of the precise coordinate from
which a popup
div
was made to animate, so that if the user goes back, it can be made
to animate to the same location. Or alternatively, it could be used to keep a pointer into a
cache of data that would be fetched from the server based on the information in the
URL
, so that when going back and forward, the information doesn't have to be fetched
again.
scroll restoration mode
indicates whether the user agent should restore the
persisted scroll position (if any) when traversing to an
entry
. A scroll restoration mode is one of the following:
auto
The user agent is responsible for restoring the scroll position upon navigation.
manual
The page is responsible for restoring the scroll position and the user agent does not
attempt to do so automatically
7.4.1.2
Document state
Document state
holds state inside a
session history entry
regarding
how to present and, if necessary, recreate, a
Document
. It has:
document
, a
Document
or null,
initially null.
When a history entry is
active
, it has a
Document
in its
document state
. However,
when a
Document
is not
fully active
, it's possible for it to be
destroyed
to free resources. In such cases, this
document
item will be nulled out. The
URL
and other data in the
session history entry
and
document state
is then used to bring a new
Document
into being to take the place of the original, in the case where the user
agent finds itself having to traverse to the entry.
If the
Document
is
not
destroyed
, then during
history
traversal
, it can be
reactivated
. The cache
in which browsers store such
Document
s is often called a
back-forward
cache
, or
bfcache
(or perhaps
"blazingly fast"
cache).
history
policy container
, a
policy container
or null, initially null.
request referrer
, which is "
no-referrer
", "
client
", or a
URL
, initially
client
".
request referrer policy
, which
is a
referrer policy
, initially the
default referrer policy
The
request referrer
policy
is distinct from the
history policy container
's
referrer policy
. The former is used for
fetches
of
this document, whereas the latter controls fetches
by
this
document.
An
initiator origin
, which is an
origin
or null, initially null.
An
origin
, which is an
origin
or
null, initially null.
This is the origin that we set "
about:
"-schemed
Document
s'
origin
to. We store it
here because it is also used when restoring these
Document
s during traversal,
since they are reconstructed locally without visiting the network. It is also used to compare
the origin before and after the
session history entry
is
repopulated
. If the origins change, the
navigable target name
is cleared.
An
about base URL
, which is a
URL
or null, initially null.
This will be populated only for "
about:
"-schemed
Document
s and will be the
fallback base URL
for those
Document
s. It is a snapshot of the initiator
Document
's
document
base URL
Nested histories
, a
list
of
nested histories
, initially an empty
list
resource
, a string,
POST resource
or null, initially null.
A string is treated as HTML. It's used to store the source of an
iframe
srcdoc
document
reload pending
boolean, initially
false.
An
ever populated
boolean, initially
false.
navigable target
name
string, initially the empty string.
not restored reasons
, a
not restored reasons
or null, initially null.
User agents may
destroy a document and its descendants
given the
documents
of
document
states
with non-null
documents
, as long as
the
Document
is not
fully active
Apart from that restriction, this standard does not specify when user agents should destroy
the
document
stored in a
document
state
, versus keeping it cached.
POST resource
has:
request body
, a
byte sequence
or failure.
This is only ever accessed
in parallel
, so it doesn't need to be stored in
memory. However, it must return the same
byte sequence
each time. If this isn't
possible due to resources changing on disk, or if resources can no longer be accessed, then
this must be set to failure.
request
content-type
, which is `
application/x-www-form-urlencoded
`,
multipart/form-data
`, or `
text/plain
`.
nested history
has:
An
id
, a
unique internal value
This is used to associate the
nested history
with a
navigable
Entries
, a
list
of
session history entries
This will later contain ways to identify a child navigable across reloads.
Several contiguous entries in a session history can share the same
document state
. This can occur when the initial entry is
reached via normal
, and the following entry is added
via
history.pushState()
. Or it can occur via
navigation to a fragment
All entries that share the same
document
state
(and that are therefore merely different states of one particular document) are
contiguous by construction.
Document
has a
latest entry
, a
session history entry
or
null.
This is the entry that was most recently represented by a given
Document
. A single
Document
can represent many
session history entries
over time, as many contiguous
session history entries
can share the same
document state
as explained above.
7.4.1.3
Centralized modifications of session history
To maintain a single source of truth, all modifications to a
traversable
navigable
's
session history entries
need
to be synchronized. This is especially important due to how session history is influenced by all
of the descendant
navigables
, and thus by multiple
event loops
. To accomplish this, we use the
session history
traversal parallel queue
structure.
session history traversal parallel queue
is
very similar to a
parallel queue
. It has an
algorithm set
, an
ordered set
The
items
in a
session history traversal parallel
queue
's
algorithm
set
are either algorithm steps, or
synchronous navigation
steps
, which are a particular brand of algorithm steps involving a
target
navigable
(a
navigable
).
To
append session history traversal
steps
to a
traversable navigable
traversable
given algorithm steps
steps
append
steps
to
traversable
's
session history
traversal queue
's
algorithm set
To
append session history synchronous
navigation steps
involving a
navigable
targetNavigable
to a
traversable navigable
traversable
given algorithm steps
steps
append
steps
as
synchronous navigation
steps
targeting
target
navigable
targetNavigable
to
traversable
's
session history traversal queue
's
algorithm set
To
start a new session history traversal parallel queue
Let
sessionHistoryTraversalQueue
be a new
session history traversal
parallel queue
Run the following steps
in parallel
While true:
If
sessionHistoryTraversalQueue
's
algorithm set
is
empty, then
continue
Let
steps
be the result of
dequeuing
from
sessionHistoryTraversalQueue
's
algorithm
set
Run
steps
Return
sessionHistoryTraversalQueue
Synchronous navigation
steps
are tagged in the
algorithm set
to allow
them to conditionally "jump the queue". This is handled
within apply the history step
Imagine the joint session history depicted by this
Jake diagram
top
/a
/b
And the following code runs at the top level:
history
back
();
location
href
'#foo'
The desired result is:
top
/a
/b
/b#foo
This isn't straightforward, as the sync navigation wins the race in terms of being
observable, whereas the traversal wins the race in terms of queuing steps on the
session
history traversal parallel queue
. To achieve this result, the following happens:
history.back()
appends steps
intended to traverse by
a delta of −1.
location.href = '#foo'
synchronously changes the
active session history entry
entry to a
newly-created one, with the URL
/b#foo
, and
appends synchronous steps
to notify
the central source of truth about that new entry. Note that this does
not
yet update
the
current session history entry
current session history step
, or the
session history entries
list; those updates cannot
be done synchronously, and instead must be done as part of the queued steps.
On the
session history traversal parallel queue
, the steps queued by
history.back()
run:
The target history step is determined to be 0: the
current session history step
(i.e., 1) plus
the intended delta of −1.
We enter the main
apply the history step
algorithm.
The entry at step 0, for the
/a
URL, has its
document
populated
Meanwhile, the queue is checked for
synchronous navigation
steps
. The steps queued by the
location.href
setter now run, and block the traversal from performing effects beyond document population
(such as, unloading documents and switching active history entries) until they are finished.
Those steps cause the following to happen:
The entry with URL
/b#foo
is added, with its
step
determined to be 2: the
current session history step
(i.e., 1) plus
1.
We fully switch to that newly added entry, including a nested call to
apply
the history step
. This ultimately results in
updating the document
by dispatching events like
hashchange
Only once that is all complete, and the
/a
history entry has been
fully populated with a
document
, do we move on with
applying the history step given the target step of 0.
At this point, the
Document
with URL
/b#foo
unloads
, and we finish moving to our target history step
0, which makes the entry with URL
/a
become the
active session history entry
and 0 become the
current session history step
Here is another more complex example, involving races between populating two different
iframe
s, and a synchronous navigation once one of those iframes loads. We start
with this setup:
top
/t
frames[0]
/i-0-a
/i-0-b
frames[1]
/i-1-a
/i-1-b
and then call
history.go(-2)
. The following then
occurs:
history.go(-2)
appends steps
intended to traverse
by a delta of −2. Once those steps run:
The target step is determined to be 2 + (−2) = 0.
In parallel, the fetches are made to
populate
the two iframes, fetching
/i-0-a
and
/i-1-a
respectively.
Meanwhile, the queue is checked for
synchronous navigation
steps
. There aren't any right now.
In the fetch race, the fetch for
/i-0-a
wins. We proceed onward
to finish all of
apply the history step
's work for how the traversal impacts the
frames[0]
navigable
, including updating its
active session history entry
to the entry with URL
/i-0-a
Before the fetch for
/i-1-a
finishes, we reach the point where
scripts may run for the newly-created document
in the
frames[0]
navigable
's
active
document
. Some such script does run:
location
href
'#foo'
This synchronously changes the
frames[0]
navigable's
active session history entry
entry to a
newly-created one, with the URL
/i-0-a#foo
, and
appends synchronous steps
to notify
the central source of truth about that new entry.
Unlike in the
previous
example
, these synchronous steps do
not
"jump the queue" and update the
traversable
before we finish the fetch for
/i-1-a
. This is because the navigable in question,
frames[0]
, has already been altered as part of the traversal, so we know
that with the
current session history
step
being 2, adding the new entry as a step 3 doesn't make sense.
Once the fetch for
/i-1-a
finally finishes, we proceed to finish
updating the
frames[1]
navigable
for the traversal,
including updating its
active session history
entry
to the entry with URL
/i-1-a
Now that both navigables have finished processing the traversal, we update the
current session history step
to the target
step of 0.
Now we can process the steps that were queued for the synchronous navigation:
The
/i-0-a#foo
entry is added, with its
step
determined to be 1: the
current session history step
(i.e., 0) plus
1. This also
clears existing forward
history
We fully switch to that newly added entry, including calling
apply the history
step
. This ultimately results in
updating the document
by dispatching events like
hashchange
, as well as updating the
current session history step
to the target
step of 1.
The end result is:
top
/t
frames[0]
/i-0-a
/i-0-a#foo
frames[1]
/i-1-a
7.4.1.4
Low-level operations on session history
This section contains a miscellaneous grab-bag of operations that we perform throughout the
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
of a
navigable
navigable
Let
traversable
be
navigable
's
traversable navigable
Assert
: this is running within
traversable
's
session history traversal queue
If
navigable
is
traversable
, return
traversable
's
session history entries
Let
docStates
be an empty
ordered set
of
document states
For each
entry
of
traversable
's
session history entries
append
entry
's
document state
to
docStates
For each
docState
of
docStates
For each
nestedHistory
of
docState
's
nested
histories
If
nestedHistory
's
id
equals
navigable
's
id
, return
nestedHistory
's
entries
For each
entry
of
nestedHistory
's
entries
append
entry
's
document state
to
docStates
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
be
startingIndex
− 1.
While
> 0:
If
rawEntries
]'s
document
state
's
origin
is not
same
origin
with
startingOrigin
, then
break
Prepend
rawEntries
] to
entriesForNavigationAPI
Set
to
− 1.
Set
to
startingIndex
+ 1.
While
rawEntries
's
size
If
rawEntries
]'s
document
state
's
origin
is not
same
origin
with
startingOrigin
, then
break
Append
rawEntries
] to
entriesForNavigationAPI
Set
to
+ 1.
Return
entriesForNavigationAPI
To
clear the forward session history
of a
traversable navigable
navigable
Assert
: this is running within
navigable
's
session history traversal queue
Let
step
be the
navigable
's
current session history step
Let
entryLists
be the
ordered set
navigable
's
session history entries
».
For each
entryList
of
entryLists
Remove
every
session history entry
from
entryList
that has a
step
greater than
step
For each
entry
of
entryList
For each
nestedHistory
of
entry
's
document state
's
nested histories
append
nestedHistory
's
entries list
to
entryLists
To
get all used history steps
that are part
of
traversable navigable
traversable
Assert
: this is running within
traversable
's
session history traversal queue
Let
steps
be an empty
ordered set
of non-negative
integers.
Let
entryLists
be the
ordered set
traversable
's
session history
entries
».
For each
entryList
of
entryLists
For each
entry
of
entryList
Append
entry
's
step
to
steps
For each
nestedHistory
of
entry
's
document state
's
nested histories
append
nestedHistory
's
entries list
to
entryLists
Return
steps
sorted
7.4.2
Certain actions cause a
navigable
to
navigate
to
a new resource.
For example,
following a hyperlink
form submission
, and the
window.open()
and
location.assign()
methods can all cause navigation.
Although in this standard the word "navigation" refers specifically to the
navigate
algorithm, this doesn't always line up with web developer or user
perceptions. For example:
The
URL and history update steps
are often used during so-called
"single-page app navigations" or "same-document navigations", but they do not trigger the
navigate
algorithm.
Reloads
and
traversals
are sometimes talked about as a type of navigation, since all three
will often
attempt to populate the history entry's document
and thus could perform
navigational fetches. See, e.g., the APIs exposed
Navigation Timing
. But they have
their own entry point algorithms, separate from the
navigate
algorithm.
[NAVIGATIONTIMING]
Although
fragment navigations
are always done
through the
navigate
algorithm, a user might perceive them as more like jumping
around a single page, than as a true navigation.
7.4.2.1
Supporting concepts
Before we can jump into the
navigation algorithm
itself, we
need to establish several important structures that it uses.
The
source snapshot params
struct
is used to capture data from a
Document
initiating a navigation. It is snapshotted at the beginning of a navigation
and used throughout the navigation's lifetime. It has the following
items
has transient activation
a boolean
sandboxing flags
sandboxing flag set
allows downloading
a boolean
fetch client
an
environment settings object
or null, only to be used as a
request client
source policy container
policy container
To
snapshot source snapshot params
given a
Document
-or-null
sourceDocument
If
sourceDocument
is null, then return a new
source snapshot params
with
has transient activation
true
sandboxing flags
an empty
sandboxing flag set
allows downloading
true
fetch client
null
source policy container
a new
policy container
This
only occurs
in the case of a
browser UI-initiated navigation.
Return a new
source snapshot params
with
has transient activation
true if
sourceDocument
's
relevant global object
has
transient
activation
; otherwise false
sandboxing flags
sourceDocument
's
active sandboxing flag set
allows downloading
false if
sourceDocument
's
active sandboxing flag set
has the
sandboxed downloads browsing context flag
set; otherwise true
fetch client
sourceDocument
's
relevant settings object
source policy container
clone
of
sourceDocument
's
policy container
The
target snapshot params
struct
is used to capture data from a
navigable
being navigated. Like
source snapshot params
, it is
snapshotted at the beginning of a navigation and used throughout the navigation's lifetime. It
has the following
items
sandboxing flags
sandboxing flag set
iframe
element referrer policy
referrer policy
To
snapshot target snapshot params
given a
navigable
targetNavigable
, return a new
target snapshot
params
with:
sandboxing flags
the result of
determining the creation sandboxing flags
given
targetNavigable
's
active browsing context
and
targetNavigable
's
container
iframe
element referrer policy
the result of
determining the
iframe
element referrer policy
given
targetNavigable
's
container
Much of the navigation process is concerned with determining how to create a new
Document
, which ultimately happens in the
create and initialize a
Document
object
algorithm. The parameters to that algorithm are tracked via a
navigation params
struct
, which has the following
items
id
null or a
navigation ID
navigable
the
navigable
to be navigated
request
null or a
request
that started the navigation
response
response
that ultimately was navigated to
(potentially a
network error
fetch
controller
null or a
fetch controller
commit early
hints
null or an algorithm accepting a
Document
, once it has been created
COOP
enforcement result
an
opener policy enforcement result
, used for
reporting and potentially for causing a
browsing context
group switch
reserved
environment
null or an
environment
reserved for the new
Document
origin
an
origin
to use for the new
Document
policy
container
policy container
to use for the new
Document
final sandboxing flag
set
sandboxing flag set
to impose on the new
Document
iframe
element referrer policy
referrer policy
, used in the
internal ancestor origin objects list
creation steps
opener policy
an
opener policy
to use for the new
Document
navigation timing
type
NavigationTimingType
used for
creating the navigation timing entry
for the new
Document
about base
URL
URL
or null used to populate the new
Document
's
about base URL
user
involvement
user navigation involvement
used when
obtaining a browsing context
for the new
Document
Once a
navigation params
struct is created, this standard does not
mutate any of its
items
. They are only passed onward to other
algorithms.
navigation ID
is a UUID string generated during navigation. It is used to
interface with the
WebDriver BiDi
specification as well as to track the
ongoing
[WEBDRIVERBIDI]
After
Document
creation, the relevant
traversable navigable
's
session history
gets updated. The
NavigationHistoryBehavior
enumeration is used to indicate the desired type of session
history update to the
navigate
algorithm. It is one of the following:
push
A regular navigation which adds a new
session history entry
, and will
clear the forward session history
replace
A navigation that will replace the
active session
history entry
auto
The default value, which will be converted very early in the
navigate
algorithm
into "
push
" or "
replace
". Usually it becomes "
push
", but under
certain circumstances
it becomes "
replace
" instead.
history handling behavior
is a
NavigationHistoryBehavior
that is
either "
push
" or "
replace
", i.e., that has been resolved away from
any initial "
auto
" value.
The navigation must be a replace
, given a
URL
url
and a
Document
document
, if any of the following are true:
url
's
scheme
is "
javascript
"; or
document
's
is initial
about:blank
is true.
Other cases that often, but not always, force a "
replace
" navigation are:
if the
Document
is not
completely loaded
; or
if the target
URL
equals the
Document
's
URL
Various parts of the platform track whether a user is involved in a navigation. A
user navigation involvement
is one of the following:
browser UI
The navigation was initiated by the user via browser UI mechanisms.
activation
The navigation was initiated by the user via the
activation behavior
of an
element.
none
The navigation was not initiated by the user.
For convenience at certain call sites, the
user navigation
involvement
for an
Event
event
is defined as follows:
Assert
: this algorithm is being called as part of an
activation
behavior
definition.
Assert
event
's
type
is
click
".
If
event
's
isTrusted
is initialized
to true, then return "
activation
".
Return "
none
".
7.4.2.2
Beginning navigation
To
navigate
navigable
navigable
to a
URL
url
using an optional
Document
-or-null
sourceDocument
(default null), with an optional
POST
resource
, string, or null
documentResource
(default null), an optional
response
-or-null
response
(default null), an optional boolean
exceptionsEnabled
(default false), an optional
NavigationHistoryBehavior
historyHandling
(default "
auto
"), an optional
serialized
state
-or-null
navigationAPIState
(default null), an optional
entry list
or
null
formDataEntryList
(default null), an optional
referrer policy
referrerPolicy
(default the empty
string), an optional
user navigation involvement
userInvolvement
(default "
none
"), an optional
Element
sourceElement
(default null), an optional
boolean
initialInsertion
(default false), and an
optional
navigation API method tracker
-or-null
apiMethodTracker
(default null):
Let
cspNavigationType
be "
form-submission
" if
formDataEntryList
is non-null; otherwise "
other
".
Let
sourceSnapshotParams
be the result of
snapshotting source snapshot
params
given
sourceDocument
Let
initiatorOriginSnapshot
be a new
opaque origin
Let
initiatorBaseURLSnapshot
be
about:blank
If
sourceDocument
is null:
Assert
userInvolvement
is
browser UI
".
If
url
's
scheme
is "
javascript
", then set
initiatorOriginSnapshot
to
navigable
's
active document
's
origin
Otherwise:
Assert
userInvolvement
is not "
browser UI
".
If
sourceDocument
's
node navigable
is not
allowed by
sandboxing to navigate
navigable
given
sourceSnapshotParams
If
exceptionsEnabled
is true, then throw a
SecurityError
DOMException
Return.
Set
initiatorOriginSnapshot
to
sourceDocument
's
origin
Set
initiatorBaseURLSnapshot
to
sourceDocument
's
document
base URL
Let
navigationId
be the result of
generating a random UUID
[WEBCRYPTO]
If the
surrounding agent
is equal to
navigable
's
active document
's
relevant agent
, then continue these
steps. Otherwise,
queue a global task
on the
navigation and traversal task
source
given
navigable
's
active window
to
continue these steps.
We do this because we are about to look at a lot of properties of
navigable
's
active document
, which are in theory only accessible over
in the appropriate
event loop
. (But, we do not want to unconditionally queue a
task, since — for example — same-event-loop
fragment navigations
need to take effect synchronously.)
Another implementation strategy would be to replicate the relevant information across event
loops, or into a canonical "browser process", so that it can be consulted without queueing a
task. This could give different results than what we specify here in edge cases, where the
relevant properties have changed over in the target event loop but not yet been replicated.
Further testing is needed to determine which of these strategies best matches browser
behavior, in such racy edge cases.
If
navigable
's
active document
's
unload counter
is greater than 0, then invoke
WebDriver BiDi navigation
failed
with
navigable
and a
WebDriver BiDi navigation status
whose
id
is
navigationId
status
is "
canceled
", and
url
is
url
, and return.
Let
container
be
navigable
's
container
If
container
is an
iframe
element and
will lazy load
element steps
given
container
returns true, then
stop
intersection-observing a lazy loading element
container
and set
container
's
lazy load resumption steps
to null.
If
historyHandling
is "
auto
",
then:
If
url
equals
navigable
's
active document
's
URL
, and
initiatorOriginSnapshot
is
same
origin
with
navigable
's
active document
's
origin
, then set
historyHandling
to
replace
".
Otherwise, set
historyHandling
to "
push
".
If
the navigation must be a replace
given
url
and
navigable
's
active document
, then set
historyHandling
to "
replace
".
If all of the following are true:
documentResource
is null;
response
is null;
url
equals
navigable
's
active session history entry
's
URL
with
exclude
fragments
set to true; and
url
's
fragment
is
non-null,
then:
Navigate to a fragment
given
navigable
url
historyHandling
userInvolvement
sourceElement
navigationAPIState
, and
navigationId
Return.
If
navigable
's
parent
is non-null, then set
navigable
's
is delaying
load
events
to
true.
Let
targetSnapshotParams
be the result of
snapshotting target snapshot
params
given
navigable
Invoke
WebDriver BiDi navigation started
with
navigable
and a new
WebDriver BiDi navigation status
whose
id
is
navigationId
status
is "
pending
", and
url
is
url
If
navigable
's
ongoing navigation
is "
traversal
", then:
Invoke
WebDriver BiDi navigation failed
with
navigable
and a new
WebDriver BiDi navigation status
whose
id
is
navigationId
status
is "
canceled
", and
url
is
url
Return.
Any attempts to navigate a
navigable
that is currently
traversing
are ignored.
Set the ongoing navigation
for
navigable
to
navigationId
This will have the effect of aborting other ongoing navigations of
navigable
, since at certain points during navigation changes to the
ongoing
will cause further work to be abandoned.
If
url
's
scheme
is "
javascript
", then:
Queue a global task
on the
navigation and traversal task
source
given
navigable
's
active window
to
navigate to a
javascript:
URL
given
navigable
url
historyHandling
sourceSnapshotParams
initiatorOriginSnapshot
userInvolvement
cspNavigationType
initialInsertion
, and
navigationId
Return.
If all of the following are true:
userInvolvement
is not "
browser
UI
";
navigable
's
active document
's
origin
is
same origin-domain
with
sourceDocument
's
origin
navigable
's
active document
's
is
initial
about:blank
is false; and
url
's
scheme
is a
fetch
scheme
then:
Let
be
navigable
's
active
window
's
navigation API
Let
entryListForFiring
be
formDataEntryList
if
documentResource
is a
POST resource
; otherwise, null.
Let
navigationAPIStateForFiring
be
navigationAPIState
if
navigationAPIState
is not null; otherwise,
StructuredSerializeForStorage
(undefined).
Let
continue
be the result of
firing a push/replace/reload
navigate
event
at
with
navigationType
set to
historyHandling
isSameDocument
set to false,
userInvolvement
set to
userInvolvement
sourceElement
set
to
sourceElement
formDataEntryList
set to
entryListForFiring
destinationURL
set to
url
navigationAPIState
set to
navigationAPIStateForFiring
, and
apiMethodTracker
set to
apiMethodTracker
If
continue
is false, then return.
It is possible for navigations with
userInvolvement
of "
browser UI
" or initiated by a
cross origin-domain
sourceDocument
to fire
navigate
events, if they go through the earlier
navigate to a fragment
path.
If
sourceDocument
is
navigable
's
container document
, then
reserve deferred fetch
quota
for
navigable
's
container
given
url
's
origin
In parallel
, run these steps:
Let
unloadPromptCanceled
be the result of
checking if unloading is
canceled
for
navigable
's
active
document
's
inclusive descendant navigables
If
unloadPromptCanceled
is not "
continue
", or
navigable
's
ongoing navigation
is no longer
navigationId
Invoke
WebDriver BiDi navigation failed
with
navigable
and a
new
WebDriver BiDi navigation status
whose
id
is
navigationId
status
is "
canceled
", and
url
is
url
Abort these steps.
Queue a global task
on the
navigation and traversal task
source
given
navigable
's
active window
to
abort a document and its descendants
given
navigable
's
active document
Let
documentState
be a new
document state
with
request referrer policy
referrerPolicy
initiator origin
initiatorOriginSnapshot
resource
documentResource
navigable target name
navigable
's
target name
The
navigable target
name
can get cleared under various conditions later in the navigation process, before
the document state is finalized.
If
url
matches
about:blank
or
is
about:srcdoc
, then:
Set
documentState
's
origin
to
initiatorOriginSnapshot
Set
documentState
's
about base
URL
to
initiatorBaseURLSnapshot
Let
historyEntry
be a new
session history entry
, with its
URL
set to
url
and its
document state
set to
documentState
Let
navigationParams
be null.
If
response
is non-null:
The
navigate
algorithm
is only supplied with a
response
as part of the
object
and
embed
processing models, or for processing parts of
multipart/x-mixed-replace
responses
after the initial response.
Let
sourcePolicyContainer
be a
clone
of the
sourceDocument
's
policy container
, if
sourceDocument
is not null; otherwise null.
Let
policyContainer
be the result of
determining navigation params policy container
given
response
's
URL
null,
sourcePolicyContainer
navigable
's
container document
's
policy container
, and null.
Let
finalSandboxFlags
be the
union
of
targetSnapshotParams
's
sandboxing
flags
and
policyContainer
's
CSP
list
's
CSP-derived sandboxing flags
Let
responseOrigin
be the result of
determining the origin
given
response
's
URL
finalSandboxFlags
, and
documentState
's
initiator origin
Let
coop
be a new
opener policy
Let
coopEnforcementResult
be a new
opener policy enforcement result
with
url
response
's
URL
origin
responseOrigin
opener policy
coop
Set
navigationParams
to a new
navigation params
, with
id
navigationId
navigable
navigable
request
null
response
response
fetch controller
null
commit early hints
null
COOP enforcement result
coopEnforcementResult
reserved environment
null
origin
responseOrigin
policy container
policyContainer
final sandboxing flag set
finalSandboxFlags
iframe
element referrer policy
targetSnapshotParams
's
iframe
element referrer
policy
opener policy
coop
navigation timing type
navigate
about base URL
documentState
's
about base
URL
user involvement
userInvolvement
Attempt to populate the history entry's document
for
historyEntry
given
navigable
, "
navigate
",
sourceSnapshotParams
targetSnapshotParams
userInvolvement
navigationId
navigationParams
cspNavigationType
, with
allowPOST
set to true and
completionSteps
set to the following
step:
Append session history
traversal steps
to
navigable
's
traversable
to
finalize a cross-document
given
navigable
historyHandling
userInvolvement
, and
historyEntry
7.4.2.3
Ending navigation
Although the usual cross-document navigation case will first foray into
populating a session history entry
with a
Document
, all navigations that don't get aborted will ultimately end up calling into
one of the below algorithms.
7.4.2.3.1
The usual cross-document navigation case
To
finalize a cross-document navigation
given a
navigable
navigable
, a
history handling behavior
historyHandling
, a
user navigation involvement
userInvolvement
, and a
session history
entry
historyEntry
Assert
: this is running on
navigable
's
traversable navigable's
session history traversal queue
Set
navigable
's
is delaying
load
events
to false.
If
historyEntry
's
document
is null, then
return.
This means that
attempting to populate the history entry's document
ended up not creating a
document, as a result of e.g., the navigation being canceled by a subsequent navigation, a 204
No Content response, etc.
If all of the following are true:
navigable
's
parent
is null;
historyEntry
's
document
's
browsing context
is not an
auxiliary browsing
context
whose
opener browsing context
is non-null; and
historyEntry
's
document
's
origin
is not
navigable
's
active document
's
origin
then set
historyEntry
's
document state
's
navigable target name
to the empty
string.
Let
entryToReplace
be
navigable
's
active session history entry
if
historyHandling
is "
replace
",
otherwise null.
Let
traversable
be
navigable
's
traversable navigable
Let
targetStep
be null.
Let
targetEntries
be the result of
getting session history
entries
for
navigable
If
entryToReplace
is null, then:
Clear the forward session history
of
traversable
Set
targetStep
to
traversable
's
current session history step
+ 1.
Set
historyEntry
's
step
to
targetStep
Append
historyEntry
to
targetEntries
Otherwise:
Replace
entryToReplace
with
historyEntry
in
targetEntries
Set
historyEntry
's
step
to
entryToReplace
's
step
If
historyEntry
's
document state
's
origin
is
same origin
with
entryToReplace
's
document state
's
origin
, then set
historyEntry
's
navigation API key
to
entryToReplace
's
navigation API key
Set
targetStep
to
traversable
's
current session history step
Apply the push/replace history step
targetStep
to
traversable
given
historyHandling
and
userInvolvement
7.4.2.3.2
The
javascript:
URL special case
javascript:
URLs have a
dedicated label
on the issue tracker documenting various problems with their specification.
To
navigate to a
javascript:
URL
, given a
navigable
targetNavigable
, a
URL
url
, a
history handling
behavior
historyHandling
, a
source snapshot params
sourceSnapshotParams
, an
origin
initiatorOrigin
, a
user
navigation involvement
userInvolvement
, a string
cspNavigationType
, a boolean
initialInsertion
, and a
ID
navigationId
Assert
historyHandling
is "
replace
".
If
targetNavigable
's
ongoing navigation
is no longer
navigationId
, then return.
Set the ongoing navigation
for
targetNavigable
to null.
If
initiatorOrigin
is not
same origin-domain
with
targetNavigable
's
active document
's
origin
, then return.
Let
request
be a new
request
whose
URL
is
url
and whose
policy container
is
sourceSnapshotParams
's
source
policy container
This is a synthetic
request
solely for
plumbing into the next step. It will never hit the network.
If the result of
should navigation request of type be blocked by Content Security
Policy?
given
request
and
cspNavigationType
is "
Blocked
", then return.
[CSP]
Let
newDocument
be the result of
evaluating a
javascript:
URL
given
targetNavigable
url
initiatorOrigin
, and
userInvolvement
If
newDocument
is null:
If
initialInsertion
is true and
targetNavigable
's
active document
's
is initial
about:blank
is true, then run the
iframe load event steps
given
targetNavigable
's
container
Return.
In this case, some JavaScript code was executed, but no new
Document
was created, so we will not perform a navigation.
Assert
initiatorOrigin
is
newDocument
's
origin
Let
entryToReplace
be
targetNavigable
's
active session history entry
Let
oldDocState
be
entryToReplace
's
document state
Let
documentState
be a new
document state
with
document
newDocument
history policy container
clone
of the
oldDocState
's
history policy container
if it is
non-null; null otherwise
request referrer
oldDocState
's
request
referrer
request referrer policy
oldDocState
's
request
referrer policy
or should this be the
referrerPolicy
that
was passed to
navigate
initiator origin
initiatorOrigin
origin
initiatorOrigin
about base URL
oldDocState
's
about base
URL
resource
null
ever populated
true
navigable target name
oldDocState
's
navigable target
name
Let
historyEntry
be a new
session history entry
, with
URL
entryToReplace
's
URL
document state
documentState
For the
URL
, we do
not
use
url
, i.e. the actual
javascript:
URL that
the
navigate
algorithm was called with. This means
javascript:
URLs are never stored in session history, and so can never be
traversed to.
Append session history traversal
steps
to
targetNavigable
's
traversable
to
finalize a cross-document navigation
with
targetNavigable
historyHandling
userInvolvement
, and
historyEntry
To
evaluate a
javascript:
URL
given a
navigable
targetNavigable
, a
URL
url
, an
origin
newDocumentOrigin
, and a
user navigation involvement
userInvolvement
Let
urlString
be the result of running the
URL serializer
on
url
Let
encodedScriptSource
be the result of removing the leading "
javascript:
" from
urlString
Let
scriptSource
be the
UTF-8 decoding
of
the
percent-decoding
of
encodedScriptSource
Let
settings
be
targetNavigable
's
active document
's
relevant settings object
Let
baseURL
be
settings
's
API base URL
Let
script
be the result of
creating a classic script
given
scriptSource
settings
baseURL
, and the
default script
fetch options
Let
evaluationStatus
be the result of
running the classic script
script
Let
result
be null.
If
evaluationStatus
is a normal completion, and
evaluationStatus
.[[Value]] is a String, then set
result
to
evaluationStatus
.[[Value]].
Otherwise, return null.
Let
response
be a new
response
with
URL
targetNavigable
's
active document
's
URL
header list
« (`
Content-Type
`, `
text/html;charset=utf-8
`) »
body
the
UTF-8 encoding
of
result
as a
body
The encoding to UTF-8 means that unpaired
surrogates
will not roundtrip, once the HTML parser decodes the
response body.
Let
policyContainer
be
targetNavigable
's
active document
's
policy container
Let
finalSandboxFlags
be
policyContainer
's
CSP list
's
CSP-derived sandboxing
flags
Let
coop
be
targetNavigable
's
active
document
's
opener policy
Let
coopEnforcementResult
be a new
opener
policy enforcement result
with
url
url
origin
newDocumentOrigin
opener policy
coop
Let
navigationParams
be a new
navigation params
, with
id
navigationId
navigable
targetNavigable
request
null
this will cause the referrer of the resulting
Document
to be null; is that correct?
response
response
fetch controller
null
commit early hints
null
COOP enforcement result
coopEnforcementResult
reserved environment
null
origin
newDocumentOrigin
policy container
policyContainer
final sandboxing flag set
finalSandboxFlags
iframe
element referrer policy
targetSnapshotParams
's
iframe
element referrer
policy
opener policy
coop
navigation timing type
navigate
about base URL
targetNavigable
's
active document
's
about base URL
user involvement
userInvolvement
Return the result of
loading an HTML document
given
navigationParams
7.4.2.3.3
Fragment navigations
To
navigate to a fragment
given a
navigable
navigable
, a
URL
url
, a
history handling behavior
historyHandling
, a
user navigation involvement
userInvolvement
an
Element
-or-null
sourceElement
, a
serialized state
-or-null
navigationAPIState
, and a
navigation ID
navigationId
Let
be
navigable
's
active
window
's
navigation API
Let
destinationNavigationAPIState
be
navigable
's
active session history entry
's
navigation API state
If
navigationAPIState
is not null, then set
destinationNavigationAPIState
to
navigationAPIState
Let
continue
be the result of
firing a push/replace/reload
navigate
event
at
with
navigationType
set to
historyHandling
isSameDocument
set
to true,
userInvolvement
set to
userInvolvement
sourceElement
set
to
sourceElement
destinationURL
set to
url
, and
navigationAPIState
set to
destinationNavigationAPIState
If
continue
is false, then return.
Let
historyEntry
be a new
session history entry
, with
URL
url
document state
navigable
's
active session history
entry
's
document state
navigation API state
destinationNavigationAPIState
scroll restoration mode
navigable
's
active session history
entry
's
scroll restoration mode
For navigations performed with
navigation.navigate()
, the value provided by the
state
option is used for the new
navigation API state
. (This will set it to the
serialization of undefined, if no value is provided for that option.) For other fragment
navigations, including user-initiated ones, the
navigation API state
is carried over from the previous
entry.
The
classic history API state
is never
carried over.
Let
entryToReplace
be
navigable
's
active session history entry
if
historyHandling
is "
replace
",
otherwise null.
Let
history
be
navigable
's
active
document
's
history object
Let
scriptHistoryIndex
be
history
's
index
Let
scriptHistoryLength
be
history
's
length
If
historyHandling
is "
push
",
then:
Set
history
's
state
to
null.
Increment
scriptHistoryIndex
Set
scriptHistoryLength
to
scriptHistoryIndex
+ 1.
Set
navigable
's
active document
's
URL
to
url
Set
navigable
's
active session history
entry
to
historyEntry
Update document for history step application
given
navigable
's
active document
historyEntry
, true,
scriptHistoryIndex
scriptHistoryLength
, and
historyHandling
This algorithm will be called twice as a result of a single fragment
navigation: once synchronously, where best-guess values
scriptHistoryIndex
and
scriptHistoryLength
are set,
history.state
is nulled out, and various events are fired; and once asynchronously, where the final values for
index and length are set,
history.state
remains
untouched, and no events are fired.
Scroll to the fragment
given
navigable
's
active document
If the scrolling fails because the
Document
is new and the
relevant
ID
has not yet been parsed, then the second
asynchronous call to
update document for history step application
will take
care of scrolling.
Let
traversable
be
navigable
's
traversable navigable
Append the following session history
synchronous navigation steps
involving
navigable
to
traversable
Finalize a same-document navigation
given
traversable
navigable
historyEntry
entryToReplace
historyHandling
, and
userInvolvement
Invoke
WebDriver BiDi fragment navigated
with
navigable
and a
new
WebDriver BiDi navigation status
whose
id
is
navigationId
url
is
url
, and
status
is "
complete
".
To
finalize a same-document navigation
given a
traversable navigable
traversable
, a
navigable
targetNavigable
, a
session
history entry
targetEntry
, a
session history entry
-or-null
entryToReplace
, a
history handling behavior
historyHandling
and a
user navigation involvement
userInvolvement
This is used by both
fragment navigations
and by the
URL and history update steps
, which are the only synchronous updates to
session history. By virtue of being synchronous, those algorithms are performed outside of the
top-level traversable
's
session
history traversal queue
. This puts them out of sync with the
top-level
traversable
's
current session history
step
, so this algorithm is used to resolve conflicts due to race conditions.
Assert
: this is running on
traversable
's
session history traversal queue
If
targetNavigable
's
active session
history entry
is not
targetEntry
, then return.
Let
targetStep
be null.
Let
targetEntries
be the result of
getting session history
entries
for
targetNavigable
If
entryToReplace
is null, then:
Clear the forward session history
of
traversable
Set
targetStep
to
traversable
's
current session history step
+ 1.
Set
targetEntry
's
step
to
targetStep
Append
targetEntry
to
targetEntries
Otherwise:
Replace
entryToReplace
with
targetEntry
in
targetEntries
Set
targetEntry
's
step
to
entryToReplace
's
step
Set
targetStep
to
traversable
's
current session history step
Apply the push/replace history step
targetStep
to
traversable
given
historyHandling
and
userInvolvement
This is done even for "
replace
" navigations, as it resolves race
conditions across multiple synchronous navigations.
7.4.2.3.4
Non-fetch schemes and external software
The input to
attempt to create a non-fetch scheme document
is the
non-fetch
scheme navigation params
struct
. It is a lightweight version of
navigation params
which only carries parameters relevant to the non-
fetch
scheme
navigation case. It has the following
items
id
null or a
navigation ID
navigable
the
navigable
experiencing the navigation
URL
URL
target snapshot sandboxing flags
the
target snapshot params
's
sandboxing flags
present during navigation
source snapshot has transient activation
a copy of the
source snapshot params
's
has transient activation
boolean present during
activation
initiator origin
an
origin
possibly for use in a user-facing prompt to confirm the invocation of
an external software package
This differs slightly from a
document
state
's
initiator origin
in that a
non-fetch scheme navigation params
's
initiator origin
follows redirects up
to the last
fetch scheme
URL in a redirect chain that ends in a non-
fetch
scheme
URL.
navigation timing type
NavigationTimingType
used for
creating the navigation timing entry
for the new
Document
(if one is
created)
user involvement
user navigation involvement
used when
obtaining a browsing context
for the new
Document
(if one is created)
To
attempt to create a non-fetch scheme document
given a
non-fetch scheme navigation params
navigationParams
Let
url
be
navigationParams
's
URL
Let
navigable
be
navigationParams
's
navigable
If
url
is to be handled using a mechanism that does not affect
navigable
, e.g., because
url
's
scheme
is handled externally, then:
Hand-off to external software
given
url
navigable
navigationParams
's
target
snapshot sandboxing flags
navigationParams
's
source snapshot has transient
activation
, and
navigationParams
's
initiator origin
Return null.
Handle
url
by displaying some sort of inline content, e.g., an error message
because the specified scheme is not one of the supported protocols, or an inline prompt to allow
the user to select
a registered
handler
for the given scheme. Return the result of
displaying the inline content
given
navigable
navigationParams
's
id
navigationParams
's
timing type
, and
navigationParams
's
user involvement
In the case of a registered handler being used,
navigate
will be
invoked with a new URL.
To
hand-off to external software
given a
URL
or
response
resource
, a
navigable
navigable
, a
sandboxing flag set
sandboxFlags
, a boolean
hasTransientActivation
, and an
origin
initiatorOrigin
, user
agents should:
If all of the following are true:
navigable
is not a
top-level traversable
sandboxFlags
has its
sandboxed custom protocols navigation browsing
context flag
set; and
sandboxFlags
has its
sandboxed top-level navigation with user
activation browsing context flag
set, or
hasTransientActivation
is
false,
then return without invoking the external software package.
Navigation inside an iframe toward external software can be seen by users as a
new popup or a new top-level navigation. That's why its is allowed in sandboxed
iframe
only when one of
allow-popups
allow-top-navigation
allow-top-navigation-by-user-activation
or
allow-top-navigation-to-custom-protocols
is specified.
Perform the appropriate handoff of
resource
while attempting to mitigate the risk
that this is an attempt to exploit the target software. For example, user agents could prompt
the user to confirm that
initiatorOrigin
is to be allowed to invoke the external
software in question. In particular, if
hasTransientActivation
is false, then the
user agent should not invoke the external software package without prior user confirmation.
For example, there could be a vulnerability in the target software's URL
handler which a hostile page would attempt to exploit by tricking a user into clicking a
link.
7.4.2.4
Preventing navigation
A couple of scenarios can intervene early in the navigation process and put the whole thing to
a halt. This can be especially exciting when multiple
navigables
are navigating at the same time, due to a session history traversal.
navigable
source
is
allowed by
sandboxing to navigate
a second
navigable
target
, given a
source snapshot params
sourceSnapshotParams
, if the following steps
return true:
If
source
is
target
, then return true.
If
source
is an ancestor of
target
, then return true.
If
target
is an ancestor of
source
, then:
If
target
is not a
top-level traversable
, then return
true.
If
sourceSnapshotParams
's
has transient activation
is true, and
sourceSnapshotParams
's
sandboxing
flags
's
sandboxed top-level navigation with user activation browsing context
flag
is set, then return false.
If
sourceSnapshotParams
's
has transient activation
is false, and
sourceSnapshotParams
's
sandboxing
flags
's
sandboxed top-level navigation without user activation browsing context
flag
is set, then return false.
Return true.
If
target
is a
top-level traversable
If
source
is the
one permitted sandboxed navigator
of
target
, then return true.
If
sourceSnapshotParams
's
sandboxing flags
's
sandboxed navigation
browsing context flag
is set, then return false.
Return true.
If
sourceSnapshotParams
's
sandboxing flags
's
sandboxed navigation
browsing context flag
is set, then return false.
Return true.
To
check if unloading is canceled
for a
list
of
navigables
navigablesThatNeedBeforeUnload
, given an optional
traversable navigable
traversable
, an optional integer
targetStep
, and an optional
user navigation involvement
userInvolvementForNavigateEvent
, run these steps. They return "
canceled-by-beforeunload
", "
canceled-by-navigate
", or
continue
".
Let
documentsToFireBeforeunload
be the
active
document
of each
item
in
navigablesThatNeedBeforeUnload
Let
unloadPromptShown
be false.
Let
finalStatus
be "
continue
".
If
traversable
was given, then:
Assert
targetStep
and
userInvolvementForNavigateEvent
were given.
Let
targetEntry
be the result of
getting the target history
entry
given
traversable
and
targetStep
If
targetEntry
is not
traversable
's
current session history entry
, and
targetEntry
's
document state
's
origin
is the
same
as
traversable
's
current session history
entry
's
document state
's
origin
, then:
In this case, we're going to fire the
navigate
event
for
traversable
here. Because
under some circumstances
it might be
canceled, we need to do this separately from
other traversal
navigate
events
, which happen later.
Additionally, because we want
beforeunload
events
to fire before
navigate
events, this means we need to
fire
beforeunload
for
traversable
here
(if applicable), instead of doing it as part of the below loop over
documentsToFireBeforeunload
Let
eventsFired
be false.
Let
needsBeforeunload
be true if
navigablesThatNeedBeforeUnload
contains
traversable
; otherwise
false.
If
needsBeforeunload
is true, then
remove
traversable
's
active document
from
documentsToFireBeforeunload
Queue a global task
on the
navigation and traversal task source
given
traversable
's
active window
to perform the
following steps:
If
needsBeforeunload
is true, then:
Let (
unloadPromptShownForThisDocument
unloadPromptCanceledByThisDocument
) be the result of running the
steps
to fire
beforeunload
given
traversable
's
active document
and
false.
If
unloadPromptShownForThisDocument
is true, then set
unloadPromptShown
to true.
If
unloadPromptCanceledByThisDocument
is true, then set
finalStatus
to "
canceled-by-beforeunload
".
If
finalStatus
is "
canceled-by-beforeunload
", then
abort these steps.
Let
be
traversable
's
active window
's
API
Let
navigateEventResult
be the result of
firing a traverse
navigate
event
at
given
targetEntry
and
userInvolvementForNavigateEvent
If
navigateEventResult
is false, then set
finalStatus
to
canceled-by-navigate
".
Set
eventsFired
to true.
Wait until
eventsFired
is true.
If
finalStatus
is not "
continue
", then return
finalStatus
Let
totalTasks
be the
size
of
documentsToFireBeforeunload
Let
completedTasks
be 0.
For each
document
of
documentsToFireBeforeunload
queue a global task
on the
navigation and traversal task source
given
document
's
relevant global object
to run the steps:
Let (
unloadPromptShownForThisDocument
unloadPromptCanceledByThisDocument
) be the result of running the
steps to fire
beforeunload
given
document
and
unloadPromptShown
If
unloadPromptShownForThisDocument
is true, then set
unloadPromptShown
to true.
If
unloadPromptCanceledByThisDocument
is true, then set
finalStatus
to "
canceled-by-beforeunload
".
Increment
completedTasks
Wait for
completedTasks
to be
totalTasks
Return
finalStatus
The
steps to fire
beforeunload
given a
Document
document
and a boolean
unloadPromptShown
are:
Let
unloadPromptCanceled
be false.
Increase the
document
's
unload counter
by 1.
Increase
document
's
relevant agent
's
event loop
's
termination nesting level
by
1.
Let
eventFiringResult
be the result of
firing
an event
named
beforeunload
at
document
's
relevant global object
, using
BeforeUnloadEvent
with the
cancelable
attribute initialized to
true.
Decrease
document
's
relevant agent
's
event loop
's
termination nesting level
by
1.
If all of the following are true:
unloadPromptShown
is false;
document
's
active sandboxing flag set
does not have its
sandboxed modals flag
set;
document
's
relevant global object
has
sticky
activation
eventFiringResult
is false, or the
returnValue
attribute of
event
is
not the empty string; and
showing an unload prompt is unlikely to be annoying, deceptive, or pointless,
then:
Set
unloadPromptShown
to true.
Let
userPromptHandler
be the result of
WebDriver BiDi user prompt
opened
with
document
's
relevant global object
beforeunload
", and "".
If
userPromptHandler
is "
dismiss
", then set
unloadPromptCanceled
to true.
If
userPromptHandler
is "
none
", then:
Ask the user to confirm that they wish to unload the document, and
pause
while waiting for the user's response.
The message shown to the user is not customizable, but instead determined by
the user agent. In particular, the actual value of the
returnValue
attribute is ignored.
If the user did not confirm the page navigation, then set
unloadPromptCanceled
to true.
Invoke
WebDriver BiDi user prompt closed
with
document
's
relevant global object
, "
beforeunload
", and true
if
unloadPromptCanceled
is false or false otherwise.
Decrease
document
's
unload counter
by 1.
Return (
unloadPromptShown
unloadPromptCanceled
).
7.4.2.5
Aborting navigation
Each
navigable
has an
ongoing navigation
which is a
navigation ID
, "
traversal
", or null, initially
null. It is used to track navigation aborting and to prevent any navigations from taking place
during
traversal
To
set the ongoing navigation
for a
navigable
navigable
to
newValue
If
navigable
's
ongoing navigation
is equal to
newValue
then return.
Inform the navigation API about aborting navigation
given
navigable
Set
navigable
's
ongoing navigation
to
newValue
7.4.3
Reloading and traversing
To
reload
navigable
navigable
given an optional
serialized state
-or-null
navigationAPIState
(default null), an
optional
user navigation involvement
userInvolvement
(default "
none
"), and an optional
navigation API method
tracker
-or-null
apiMethodTracker
(default null):
If
userInvolvement
is not "
browser UI
",
then:
Let
be
navigable
's
active
window
's
navigation API
Let
destinationNavigationAPIState
be
navigable
's
active session history entry
's
navigation API state
If
navigationAPIState
is not null, then set
destinationNavigationAPIState
to
navigationAPIState
Let
continue
be the result of
firing a push/replace/reload
navigate
event
at
with
navigationType
set to "
reload
",
isSameDocument
set to false,
userInvolvement
set to
userInvolvement
destinationURL
set to
navigable
's
active session history
entry
's
URL
navigationAPIState
set to
destinationNavigationAPIState
, and
apiMethodTracker
set to
apiMethodTracker
If
continue
is false, then return.
Set
navigable
's
active session history
entry
's
document state
's
reload pending
to true.
Let
traversable
be
navigable
's
traversable navigable
Append the following session
history traversal steps
to
traversable
Apply the reload history step
to
traversable
given
userInvolvement
To
traverse the history by a delta
given a
traversable navigable
traversable
, an integer
delta
, and an optional
Document
sourceDocument
Let
sourceSnapshotParams
and
initiatorToCheck
be null.
Let
userInvolvement
be "
browser
UI
".
If
sourceDocument
is given, then:
Set
sourceSnapshotParams
to the result of
snapshotting source snapshot
params
given
sourceDocument
Set
initiatorToCheck
to
sourceDocument
's
node
navigable
Set
userInvolvement
to "
none
".
Append the following session
history traversal steps
to
traversable
Let
allSteps
be the result of
getting all used history steps
for
traversable
Let
currentStepIndex
be the index of
traversable
's
current session history step
within
allSteps
Let
targetStepIndex
be
currentStepIndex
plus
delta
If
allSteps
targetStepIndex
] does not
exist
, then abort these steps.
Apply the traverse history step
allSteps
targetStepIndex
] to
traversable
, given
sourceSnapshotParams
initiatorToCheck
, and
userInvolvement
7.4.4
Non-fragment synchronous "navigations"
Apart from the
navigate
algorithm,
session
history entries
can be pushed or replaced via one more mechanism, the
URL and
history update steps
. The most well-known callers of these steps are the
history.replaceState()
and
history.pushState()
APIs, but various other parts of the
standard also need to perform updates to the
active
history entry
, and they use these steps to do so.
The
URL and history update steps
, given a
Document
document
, a
URL
newURL
, an optional
serialized
state
-or-null
serializedData
(default
null), and an optional
history handling behavior
historyHandling
(default "
replace
"), are:
Let
navigable
be
document
's
node navigable
Let
activeEntry
be
navigable
's
active session history entry
Let
newEntry
be a new
session history entry
, with
URL
newURL
serialized state
if
serializedData
is not null,
serializedData
; otherwise
activeEntry
's
classic history API
state
document state
activeEntry
's
document state
scroll restoration mode
activeEntry
's
scroll restoration
mode
persisted user state
activeEntry
's
persisted user state
If
document
's
is initial
about:blank
is true, then set
historyHandling
to "
replace
".
This means that
pushState()
on an
initial
about:blank
Document
behaves as a
replaceState()
call.
Let
entryToReplace
be
activeEntry
if
historyHandling
is
replace
", otherwise null.
If
historyHandling
is "
push
",
then:
Increment
document
's
history object
's
index
Set
document
's
history object
's
length
to its
index
+ 1.
These are temporary best-guess values for immediate synchronous access.
If
serializedData
is not null, then
restore the history object
state
given
document
and
newEntry
Set the URL
given
document
to
newURL
Since this is neither a
nor a
history traversal
, it does not cause a
hashchange
event to be fired.
Set
document
's
latest entry
to
newEntry
Set
navigable
's
active session history
entry
to
newEntry
Update the navigation API entries for a same-document navigation
given
document
's
relevant global object
's
navigation API
newEntry
, and
historyHandling
Let
traversable
be
navigable
's
traversable navigable
Append the following session history
synchronous navigation steps
involving
navigable
to
traversable
Finalize a same-document navigation
given
traversable
navigable
newEntry
entryToReplace
historyHandling
, and "
none
".
Invoke
WebDriver BiDi history updated
with
navigable
Although both
fragment navigation
and the
URL and history update steps
perform synchronous history updates, only fragment
navigation contains a synchronous call to
update document for history step
application
. The
URL and history update steps
instead perform a few select
updates inside the above algorithm, omitting others. This is somewhat of an unfortunate
historical accident, and generally leads to
web-developer sadness
about the
inconsistency. For example, this means that
popstate
events
fire for fragment navigations, but not for
history.pushState()
calls.
7.4.5
Populating a session history entry
As explained in
the overview
, both
and
traversal
involve creating a
session history
entry
and then attempting to populate its
document
member, so that it can be presented inside the
navigable
This involves either: using
an already-given
response
; using the
srcdoc resource
stored in
the
session history entry
; or
fetching
. The process has several failure modes, which can either result in
doing nothing (leaving the
navigable
on its currently-
active
Document
) or can result in populating the
session history entry
with an
error
document
To
attempt to populate the history entry's document
for a
session history
entry
entry
, given a
navigable
navigable
, a
NavigationTimingType
navTimingType
, a
source snapshot params
sourceSnapshotParams
, a
target snapshot params
targetSnapshotParams
, a
user navigation involvement
userInvolvement
, an optional
navigation ID
-or-null
navigationId
(default null), an optional
navigation params
-or-null
navigationParams
(default null), an optional string
cspNavigationType
(default "
other
"), an optional boolean
allowPOST
(default false), and optional
algorithm steps
completionSteps
(default an empty
algorithm):
Assert
: this is running
in parallel
Assert
: if
navigationParams
is non-null, then
navigationParams
's
response
is
non-null.
Let
documentResource
be
entry
's
document state
's
resource
If
navigationParams
is null, then:
If
documentResource
is a string, then set
navigationParams
to the
result of
creating navigation
params from a srcdoc resource
given
entry
navigable
targetSnapshotParams
userInvolvement
navigationId
, and
navTimingType
Otherwise, if all of the following are true:
entry
's
URL
's
scheme
is a
fetch scheme
; and
documentResource
is null, or
allowPOST
is true and
documentResource
's
request body
is not failure,
then set
navigationParams
to the result of
creating navigation params by fetching
given
entry
navigable
sourceSnapshotParams
targetSnapshotParams
cspNavigationType
userInvolvement
navigationId
, and
navTimingType
Otherwise, if
entry
's
URL
's
scheme
is not a
fetch scheme
, then set
navigationParams
to a new
non-fetch scheme navigation params
with
id
navigationId
navigable
navigable
URL
entry
's
URL
target snapshot sandboxing flags
targetSnapshotParams
's
sandboxing flags
source snapshot has transient activation
sourceSnapshotParams
's
has
transient activation
initiator origin
entry
's
document state
's
initiator origin
navigation timing type
navTimingType
user involvement
userInvolvement
Queue a global task
on the
navigation and traversal task source
given
navigable
's
active window
, to run these steps:
If
navigable
's
ongoing navigation
no longer equals
navigationId
, then run
completionSteps
and abort these steps.
Let
saveExtraDocumentState
be true.
Usually, in the cases where we end up populating
entry
's
document state
's
document
, we then want to save some of the state
from that
Document
into
entry
. This ensures that if there are future
traversals to
entry
where its
document
has been
destroyed
, we can use that state when creating a new
Document
However, in some specific cases, saving the state would be unhelpful. For those, we set
saveExtraDocumentState
to false later in this algorithm.
If
navigationParams
is a
non-fetch scheme navigation params
then:
Set
entry
's
document state
's
document
to the result of running
attempt to
create a non-fetch scheme document
given
navigationParams
This can result in setting
entry
's
document state
's
document
to null, e.g., when
handing-off to external software
Set
saveExtraDocumentState
to false.
Otherwise, if any of the following are true:
navigationParams
is null;
the result of
should navigation response to navigation request of type in
target be blocked by Content Security Policy?
given
navigationParams
's
request
navigationParams
's
response
navigationParams
's
policy container
's
CSP list
cspNavigationType
, and
navigable
is "
Blocked
";
navigationParams
's
reserved environment
is non-null and
the result of
checking a navigation response's adherence to its embedder policy
given
navigationParams
's
response
navigable
, and
navigationParams
's
policy container
's
embedder policy
is false; or
the result of
checking a navigation response's adherence to
X-Frame-Options
given
navigationParams
's
response
navigable
navigationParams
's
policy
container
's
CSP list
, and
navigationParams
's
origin
is
false,
then:
Set
entry
's
document state
's
document
to the result of
creating a document for inline content that doesn't have a
DOM
, given
navigable
, null,
navTimingType
, and
userInvolvement
. The inline content should indicate to the user the sort of error
that occurred.
Make document unsalvageable
given
entry
's
document state
's
document
and "
navigation-failure
".
Set
saveExtraDocumentState
to false.
If
navigationParams
is not null, then:
Run the
environment discarding
steps
for
navigationParams
's
reserved environment
Invoke
WebDriver BiDi navigation failed
with
navigable
and a
new
WebDriver BiDi navigation status
whose
id
is
navigationId
status
is "
canceled
", and
url
is
navigationParams
's
response
's
URL
Otherwise, if
navigationParams
's
response
has a `
Content-Disposition
` header specifying the
attachment
disposition type, then:
Let
sourceAllowsDownloading
be
sourceSnapshotParams
's
allows downloading
Let
targetAllowsDownloading
be false if
navigationParams
's
final sandboxing flag set
has the
sandboxed downloads browsing context flag
set; otherwise true.
Let
uaAllowsDownloading
be true.
Optionally, the user agent may set
uaAllowsDownloading
to false, if it
believes doing so would safeguard the user from a potentially hostile download.
If
sourceAllowsDownloading
targetAllowsDownloading
, and
uaAllowsDownloading
are true, then:
Handle as a download
navigationParams
's
response
with
navigable
and
navigationId
This branch leaves
entry
's
document state
's
document
as null.
Otherwise, if
navigationParams
's
response
's
status
is not 204 and is not 205, then set
entry
's
document state
's
document
to the result of
loading a
document
given
navigationParams
sourceSnapshotParams
, and
entry
's
document state
's
initiator origin
This can result in setting
entry
's
document state
's
document
to null, e.g., when
handing-off to external software
If
entry
's
document state
's
document
is not null, then:
Set
entry
's
document state
's
ever populated
to true.
If
saveExtraDocumentState
is true:
Let
document
be
entry
's
document state
's
document
Set
entry
's
document state
's
origin
to
document
's
origin
If
document
's
URL
requires storing the policy container in history
, then:
Assert
navigationParams
is a
params
(i.e., neither null nor a
non-fetch scheme navigation
params
).
Set
entry
's
document state
's
history policy container
to
navigationParams
's
policy container
If
entry
's
document state
's
request referrer
is "
client
", and
navigationParams
is a
params
(i.e., neither null nor a
non-fetch scheme navigation params
),
then:
Assert
navigationParams
's
request
is not null.
Set
entry
's
document state
's
request referrer
to
navigationParams
's
request
's
referrer
Run
completionSteps
To
create navigation params from a srcdoc resource
given a
session history
entry
entry
, a
navigable
navigable
, a
target
snapshot params
targetSnapshotParams
, a
user navigation involvement
userInvolvement
, a
navigation ID
-or-null
navigationId
, and a
NavigationTimingType
navTimingType
Let
documentResource
be
entry
's
document state
's
resource
Let
response
be a new
response
with
URL
about:srcdoc
header list
« (`
Content-Type
`, `
text/html
`) »
body
the
UTF-8 encoding
of
documentResource
as a body
Let
responseOrigin
be the result of
determining the origin
given
response
's
URL
targetSnapshotParams
's
sandboxing
flags
, and
entry
's
document state
's
origin
Let
coop
be a new
opener policy
Let
coopEnforcementResult
be a new
opener
policy enforcement result
with
url
response
's
URL
origin
responseOrigin
opener policy
coop
Let
policyContainer
be the result of
determining navigation params policy container
given
response
's
URL
entry
's
document state
's
history policy container
, null,
navigable
's
container document
's
policy container
, and null.
Return a new
navigation params
, with
id
navigationId
navigable
navigable
request
null
response
response
fetch controller
null
commit early hints
null
COOP enforcement result
coopEnforcementResult
reserved environment
null
origin
responseOrigin
policy container
policyContainer
final sandboxing flag set
targetSnapshotParams
's
sandboxing
flags
iframe
element referrer policy
targetSnapshotParams
's
iframe
element referrer
policy
opener policy
coop
navigation timing type
navTimingType
about base URL
entry
's
document state
's
about base URL
user involvement
userInvolvement
To
create navigation params by fetching
given a
session history entry
entry
, a
navigable
navigable
, a
source snapshot params
sourceSnapshotParams
, a
target snapshot params
targetSnapshotParams
, a string
cspNavigationType
, a
user navigation involvement
userInvolvement
, a
navigation ID
-or-null
navigationId
, and a
NavigationTimingType
navTimingType
, perform the following steps. They
return a
navigation params
, a
non-fetch scheme navigation params
, or
null.
This algorithm mutates
entry
Assert
: this is running
in parallel
Let
documentResource
be
entry
's
document state
's
resource
Let
request
be a new
request
, with
url
entry
's
URL
client
sourceSnapshotParams
's
fetch
client
destination
document
The destination is updated below when
navigable
has a
container
credentials mode
include
use-URL-credentials flag
set
redirect mode
manual
replaces client id
navigable
's
active document
's
relevant
settings object
's
id
mode
navigate
referrer
entry
's
document state
's
request referrer
referrer policy
entry
's
document state
's
request referrer policy
policy container
sourceSnapshotParams
's
source policy container
traversable for user prompts
navigable
's
top-level traversable
If
navigable
is a
top-level traversable
, then set
request
's
top-level navigation initiator origin
to
entry
's
document state
's
initiator origin
If
request
's
client
is null:
This
only occurs
in the case of a
browser UI-initiated navigation.
Set
request
's
origin
to a new
opaque origin
Set
request
's
service-workers mode
to "
all
".
Set
request
's
referrer
to
no-referrer
".
If
documentResource
is a
POST resource
Set
request
's
method
to `
POST
`.
Set
request
's
body
to
documentResource
's
request
body
Set
Content-Type
to
documentResource
's
request
content-type
in
request
's
header
list
If
entry
's
document state
's
reload pending
is true, then set
request
's
reload-navigation
flag
Otherwise, if
entry
's
document
state
's
ever populated
is true, then
set
request
's
history-navigation flag
If
sourceSnapshotParams
's
has
transient activation
is true, then set
request
's
user-activation
to true.
If
navigable
's
container
is non-null:
If the
navigable
's
container
has a
browsing context scope origin
, then set
request
's
origin
to that
browsing context scope
origin
Set
request
's
destination
to
navigable
's
container
's
local name
If
sourceSnapshotParams
's
fetch
client
is
navigable
's
container
document
's
relevant settings object
, then set
request
's
initiator type
to
navigable
's
container
's
local
name
This ensure that only container-initiated navigations are reported to
resource timing.
Let
response
be null.
Let
responseOrigin
be null.
Let
fetchController
be null.
Let
coopEnforcementResult
be a new
opener
policy enforcement result
, with
url
navigable
's
active document
's
URL
origin
navigable
's
active document
's
origin
opener policy
navigable
's
active document
's
opener policy
current context is navigation source
true if
navigable
's
active document
's
origin
is
same origin
with
entry
's
document state
's
initiator origin
otherwise false
Let
finalSandboxFlags
be an empty
sandboxing flag set
Let
responsePolicyContainer
be null.
Let
responseCOOP
be a new
opener policy
Let
locationURL
be null.
Let
currentURL
be
request
's
current URL
Let
commitEarlyHints
be null.
While true:
If
request
's
reserved
client
is not null and
currentURL
's
origin
is not the
same
as
request
's
reserved
client
's
creation URL
's
origin
, then:
Run the
environment discarding steps
for
request
's
reserved client
Set
request
's
reserved
client
to null.
Set
commitEarlyHints
to null.
Preloaded links from
early hint headers
remain in the preload cache after a
same origin
redirect, but get discarded
when the redirect is cross-origin.
If
request
's
reserved
client
is null, then:
Let
topLevelCreationURL
be
currentURL
Let
topLevelOrigin
be null.
If
navigable
is not a
top-level traversable
, then:
Let
parentEnvironment
be
navigable
's
parent
's
active document
's
relevant settings object
Set
topLevelCreationURL
to
parentEnvironment
's
top-level creation URL
Set
topLevelOrigin
to
parentEnvironment
's
top-level
origin
Set
request
's
reserved
client
to a new
environment
whose
id
is a unique opaque string,
target browsing context
is
navigable
's
active browsing context
creation URL
is
currentURL
top-level creation URL
is
topLevelCreationURL
, and
top-level
origin
is
topLevelOrigin
The created environment's
active service worker
is set in
the
Handle Fetch
algorithm during the fetch
if the request URL matches a service worker registration.
[SW]
If the result of
should navigation request of type be blocked by Content Security
Policy?
given
request
and
cspNavigationType
is "
Blocked
", then set
response
to a
network error
and
break
[CSP]
Set
response
to null.
If
fetchController
is null, then set
fetchController
to the result
of
fetching
request
, with
processEarlyHintsResponse
set to
processEarlyHintsResponse
as defined below,
processResponse
set to
processResponse
as defined
below, and
useParallelQueue
set to true.
Let
processEarlyHintsResponse
be the following algorithm given a
response
earlyResponse
If
commitEarlyHints
is null, then set
commitEarlyHints
to the
result of
processing early hint headers
given
earlyResponse
and
request
's
reserved client
Let
processResponse
be the following algorithm given a
response
fetchedResponse
Set
response
to
fetchedResponse
Otherwise,
process the next manual redirect
for
fetchController
This will result in calling the
processResponse
we supplied above, during our first iteration
through the loop, and thus setting
response
Navigation handles redirects manually as navigation is the only place in the
web platform that cares for redirects to
mailto:
URLs
and such.
Wait until either
response
is non-null, or
navigable
's
ongoing
changes to no longer equal
navigationId
If the latter condition occurs, then
abort
fetchController
, and return.
Otherwise, proceed onward.
If
request
's
body
is null, then set
entry
's
document state
's
resource
to null.
Fetch unsets the
body
for
particular redirects.
Set
responsePolicyContainer
to the result of
creating a policy
container from a fetch response
given
response
and
request
's
reserved client
Set
finalSandboxFlags
to the
union
of
targetSnapshotParams
's
sandboxing
flags
and
responsePolicyContainer
's
CSP list
's
CSP-derived sandboxing
flags
Set
responseOrigin
to the result of
determining the origin
given
response
's
URL
finalSandboxFlags
, and
entry
's
document state
's
initiator origin
If
response
is a redirect, then
response
's
URL
will be the URL that led to the redirect to
response
's
location URL
; it
will not be the
location URL
itself.
If
navigable
is a
top-level traversable
, then:
Set
responseCOOP
to the result of
obtaining an
opener policy
given
response
and
request
's
reserved client
Set
coopEnforcementResult
to the result of
enforcing the response's opener policy
given
navigable
's
active browsing context
response
's
URL
responseOrigin
responseCOOP
coopEnforcementResult
, and
request
's
referrer
If
finalSandboxFlags
is not empty and
responseCOOP
's
value
is not "
unsafe-none
", then set
response
to an
appropriate
network error
and
break
This results in a network error as one cannot simultaneously provide a clean
slate to a response using opener policy and sandbox the result of
navigating to that response.
If
response
is not a
network error
navigable
is a
child navigable
, and the result of performing a
cross-origin resource
policy check
with
navigable
's
container document
's
origin
navigable
's
container document
's
relevant settings
object
request
's
destination
response
, and true is
blocked
, then set
response
to a
network error
and
break
Here we're running the
cross-origin resource policy check
against the
parent navigable
rather than
navigable
itself. This is because we care about the same-originness of the
embedded content against the parent context, not the navigation source.
Set
locationURL
to
response
's
location URL
given
currentURL
's
fragment
If
locationURL
is failure or null, then
break
Assert
locationURL
is a
URL
Set
entry
's
classic history API
state
to
StructuredSerializeForStorage
(null).
Let
oldDocState
be
entry
's
document state
Set
entry
's
document state
to a new
document state
, with
history policy container
clone
of the
oldDocState
's
history policy container
if it
is non-null; null otherwise
request referrer
oldDocState
's
request
referrer
request referrer policy
oldDocState
's
request
referrer policy
initiator origin
oldDocState
's
initiator
origin
origin
oldDocState
's
origin
about base URL
oldDocState
's
about base URL
resource
oldDocState
's
resource
ever populated
oldDocState
's
ever
populated
navigable target name
oldDocState
's
navigable target
name
For the navigation case, only
entry
referenced
oldDocState
, which was created
early
in the navigate algorithm
. So for navigations, this is functionally just an update to
entry
's
document state
. For the traversal
case, it's possible adjacent
session history
entries
also reference
oldDocState
, in which case they will continue doing
so even after we've updated
entry
's
document
state
oldDocState
's
history policy container
is only ever
non-null here in the traversal case, after we've populated it during a navigation to a URL
that
requires storing the policy container in history
The setup is given by the following
Jake diagram
top
/a
/a#foo
/a#bar
/b
Also assume that the
document state
shared by
the entries in steps 0, 1, and 2 has a null
document
, i.e.,
bfcache
is not in play.
Now consider the scenario where we traverse back to step 2, but this time when fetching
/a
, the server responds with a `
Location
header pointing to
/c
. That is,
locationURL
points to
/c
and so we have reached this step instead of
breaking
out of the loop.
In this case, we replace the
document state
of
the
session history entry
occupying step 2, but we do
not
replace the
document state of the entries occupying steps 0 and 1. The resulting
Jake
diagram
looks like this:
top
/a
/a#foo
/c#bar
/b
Note that we perform this replacement even if we end up in a redirect chain back to the
original URL, for example if
/c
itself had a `
Location
` header pointing to
/a
. Such a case would
end up like so:
top
/a
/a#foo
/a#bar
/b
If
locationURL
's
scheme
is not an
HTTP(S) scheme
, then:
Set
entry
's
document state
's
resource
to null.
Break
Set
currentURL
to
locationURL
Set
entry
's
URL
to
currentURL
By the end of this loop we will be in one of these scenarios:
locationURL
is failure, because of an unparseable `
Location
` header.
locationURL
is null, either because
response
is a
network
error
or because we successfully fetched a non-
network error
HTTP(S)
response with no `
Location
` header.
locationURL
is a
URL
with a non-
HTTP(S)
scheme
If
locationURL
is a
URL
whose
scheme
is not a
fetch scheme
, then return a new
non-fetch scheme navigation params
, with
id
navigationId
navigable
navigable
URL
locationURL
target snapshot sandboxing flags
targetSnapshotParams
's
sandboxing
flags
source snapshot has transient activation
sourceSnapshotParams
's
has
transient activation
initiator origin
responseOrigin
navigation timing type
navTimingType
user involvement
userInvolvement
At this point,
request
's
current URL
is the last
URL
in the
redirect chain with a
fetch
scheme
before redirecting to a non-
fetch scheme
URL
. It is this
URL
's
origin
that will be used as the initiator origin for navigations to non-
fetch scheme
URLs
If any of the following are true:
response
is a
network error
locationURL
is failure; or
locationURL
is a
URL
whose
scheme
is a
fetch scheme
then return null.
We allow redirects to non-
fetch scheme
URLs
, but redirects to
fetch scheme
URLs
that aren't
HTTP(S)
are treated
like network errors.
Assert
locationURL
is null and
response
is not a
network error
Let
resultPolicyContainer
be the result of
determining navigation params
policy container
given
response
's
URL
entry
's
document state
's
history policy container
sourceSnapshotParams
's
source
policy container
, null, and
responsePolicyContainer
If
navigable
's
container
is an
iframe
, and
response
's
timing allow passed flag
is set, then
set
navigable
's
container
's
pending resource-timing start time
to
null.
If the
iframe
is allowed to report to resource timing,
we don't need to run its fallback steps as the normal reporting would happen.
Return a new
navigation params
, with
id
navigationId
navigable
navigable
request
request
response
response
fetch controller
fetchController
commit early hints
commitEarlyHints
opener policy
responseCOOP
reserved environment
request
's
reserved client
origin
responseOrigin
policy container
resultPolicyContainer
final sandboxing flag set
finalSandboxFlags
COOP enforcement result
coopEnforcementResult
navigation timing type
navTimingType
about base URL
entry
's
document state
's
about base URL
user involvement
userInvolvement
An element has a
browsing context scope origin
if its
Document
's
node navigable
is a
top-level traversable
or if all of its
Document
's
ancestor navigables
have
active documents
whose
origins
are the
same origin
as the element's
node document
's
origin
. If an element
has a
browsing context scope origin
, then its value is the
origin
of the element's
node document
This definition is broken and needs investigation to see what it was intended to
express: see
issue #4703
To
load a document
given
navigation params
navigationParams
source snapshot params
sourceSnapshotParams
and
origin
initiatorOrigin
, perform the following steps. They return a
Document
or null.
Let
type
be the
computed type
of
navigationParams
's
response
If the user agent has been configured to process resources of the given
type
using some mechanism other than rendering the content in a
navigable
, then
skip this step. Otherwise, if the
type
is one of the following types:
an
HTML MIME type
Return the result of
loading an HTML document
, given
navigationParams
an
XML MIME type
that is not an
explicitly supported XML MIME
type
Return the result of
loading an XML document
given
navigationParams
and
type
JavaScript MIME type
JSON MIME type
that is not an
explicitly supported JSON MIME
type
text/css
text/plain
text/vtt
Return the result of
loading a text document
given
navigationParams
and
type
multipart/x-mixed-replace
Return the result of
loading a
multipart/x-mixed-replace
document
, given
navigationParams
sourceSnapshotParams
, and
initiatorOrigin
a supported image, video, or audio type
Return the result of
loading a media document
given
navigationParams
and
type
application/pdf
text/pdf
If the user agent's
PDF viewer supported
is true, return the result of
creating a document for inline content that doesn't have a
DOM
given
navigationParams
's
navigable
navigationParams
's
id
navigationParams
's
navigation timing type
, and
navigationParams
's
user
involvement
Otherwise, proceed onward.
An
explicitly supported XML MIME type
is an
XML MIME type
for which
the user agent is configured to use an external application to render the content, or for which
the user agent has dedicated processing rules. For example, a web browser with a built-in Atom
feed viewer would be said to explicitly support the
application/atom+xml
MIME
type.
An
explicitly supported JSON MIME type
is a
JSON MIME type
for which
the user agent is configured to use an external application to render the content, or for which
the user agent has dedicated processing rules.
In both cases, the external application or user agent will either
display the content inline
directly in
navigationParams
's
navigable
, or
hand it off to external software
. Both
happen in the steps below.
If, given
type
, the new resource is to be handled
by displaying some sort of inline content, e.g., a native rendering of the content or an error
message because the specified type is not supported, then return the result of
creating a document for inline content that doesn't have a
DOM
given
navigationParams
's
navigable
navigationParams
's
id
navigationParams
's
navigation timing type
, and
navigationParams
's
user
involvement
Otherwise, the document's
type
is such that the resource will not affect
navigationParams
's
navigable
, e.g.,
because the resource is to be handed to an external application or because it is an unknown type
that will be processed by
handle as a download
Hand-off to external
software
given
navigationParams
's
response
navigationParams
's
navigable
navigationParams
's
final sandboxing flag set
sourceSnapshotParams
's
has transient
activation
, and
initiatorOrigin
Return null.
7.4.6
Applying the history step
For both navigation and traversal, once we have an idea of where we want to head to in the
session history, much of the work comes about in applying that notion to the
traversable
navigable
and the relevant
Document
. For navigations, this work generally
occurs toward the end of the process; for traversals, it is the beginning.
7.4.6.1
Updating the traversable
Ensuring a
traversable
ends up at the right
session history step is particularly complex, as it can involve coordinating across multiple
navigable
descendants of the traversable,
populating
them in parallel, and then
synchronizing back up to ensure everyone has the same view of the result. This is further
complicated by the existence of synchronous same-document navigations being mixed together with
cross-document navigations, and how web pages have come to have certain relative timing
expectations.
changing navigable continuation state
is used to store information during the
apply the history step
algorithm, allowing parts of the algorithm to continue only
after other parts have finished. It is a
struct
with:
displayed document
Document
target entry
session history entry
navigable
navigable
update only
A boolean
Although all updates to the
traversable navigable
end up in the same
apply
the history step
algorithm, each possible entry point comes along with some minor
customizations:
To
update for navigable creation/destruction
given a
traversable
navigable
traversable
Let
step
be
traversable
's
current session history step
Return the result of
applying the history
step
step
to
traversable
given false, null, null, "
none
", and null.
To
apply the push/replace history step
given a non-negative integer
step
to a
traversable navigable
traversable
, given a
history handling
behavior
historyHandling
and a
user navigation involvement
userInvolvement
Return the result of
applying the history
step
step
to
traversable
given false, null, null,
userInvolvement
, and
historyHandling
Apply the push/replace history step
never passes
source
snapshot params
or an initiator
navigable
to
apply the history
step
. This is because those checks are done earlier in the
algorithm.
To
apply the reload history step
to a
traversable navigable
traversable
given
user navigation involvement
userInvolvement
Let
step
be
traversable
's
current session history step
Return the result of
applying the history
step
step
to
traversable
given true, null, null,
userInvolvement
, and "
reload
".
Apply the reload history step
never passes
source snapshot
params
or an initiator
navigable
to
apply the history step
. This
is because reloading is always treated as if it were done by the
navigable
itself,
even in cases like
parent.location.reload()
To
apply the traverse history step
given a non-negative integer
step
to a
traversable navigable
traversable
, with
source snapshot
params
sourceSnapshotParams
navigable
initiatorToCheck
and
user navigation involvement
userInvolvement
Return the result of
applying the history
step
step
to
traversable
given true,
sourceSnapshotParams
initiatorToCheck
userInvolvement
, and "
traverse
".
To
resume applying the traverse history step
given a non-negative integer
step
, a
traversable navigable
traversable
, and
user
navigation involvement
userInvolvement
apply
step
to
traversable
given false, null, null,
userInvolvement
, and "
traverse
".
When resuming a traverse, we are already past the cancelation, initiator, and
source snapshot checks, and this traversal has already been determined to be a same-document
traversal. Hence, we can pass false and null for those arguments.
Now for the algorithm itself.
To
apply the history step
given a
non-negative integer
step
to a
traversable navigable
traversable
, with boolean
checkForCancelation
source snapshot
params
-or-null
sourceSnapshotParams
navigable
-or-null
initiatorToCheck
user navigation involvement
userInvolvement
and
NavigationType
-or-null
navigationType
, perform the following steps.
They return "
initiator-disallowed
", "
canceled-by-beforeunload
", "
canceled-by-navigate
", or
applied
".
Assert
: This is running within
traversable
's
session history traversal queue
Let
targetStep
be the result of
getting the used step
given
traversable
and
step
If
initiatorToCheck
is not null, then:
Assert
sourceSnapshotParams
is not null.
For each
navigable
of
get all
navigables whose current session history entry will change or reload
: if
initiatorToCheck
is not
allowed by sandboxing to navigate
navigable
given
sourceSnapshotParams
, then return "
initiator-disallowed
".
Let
navigablesCrossingDocuments
be the result of
getting all navigables
that might experience a cross-document traversal
given
traversable
and
targetStep
If
checkForCancelation
is true, and the result of
checking if unloading
is canceled
given
navigablesCrossingDocuments
traversable
targetStep
, and
userInvolvement
is not "
continue
",
then return that result.
Let
changingNavigables
be the result of
get all navigables whose current
session history entry will change or reload
given
traversable
and
targetStep
Let
nonchangingNavigablesThatStillNeedUpdates
be the result of
getting
all navigables that only need history object length/index update
given
traversable
and
targetStep
For each
navigable
of
changingNavigables
Let
targetEntry
be the result of
getting the target history
entry
given
navigable
and
targetStep
Set
navigable
's
current session
history entry
to
targetEntry
Set the ongoing navigation
for
navigable
to "
traversal
".
Let
totalChangeJobs
be the
size
of
changingNavigables
Let
completedChangeJobs
be 0.
Let
changingNavigableContinuations
be an empty
queue
of
changing navigable continuation
states
This queue is used to split the operations on
changingNavigables
into two parts. Specifically,
changingNavigableContinuations
holds data for the
second part
For each
navigable
of
changingNavigables
queue a global task
on the
navigation and
traversal task source
of
navigable
's
active
window
to run the steps:
This set of steps are split into two parts to allow synchronous navigations to
be processed before documents unload. State is stored in
changingNavigableContinuations
for the
second
part
Let
displayedEntry
be
navigable
's
active session history entry
Let
targetEntry
be
navigable
's
current session history entry
Let
changingNavigableContinuation
be a
changing navigable continuation
state
with:
displayed document
displayedEntry
's
document
target entry
targetEntry
navigable
navigable
update-only
false
If
displayedEntry
is
targetEntry
and
targetEntry
's
document state
's
reload pending
is false, then:
Set
changingNavigableContinuation
's
update-only
to true.
Enqueue
changingNavigableContinuation
on
changingNavigableContinuations
Abort these steps.
This case occurs due to a
synchronous navigation
which already updated the
active session history entry
Switch on
navigationType
reload
Assert
targetEntry
's
document state
's
reload pending
is true.
traverse
Assert
targetEntry
's
document state
's
ever populated
is true.
replace
Assert
targetEntry
's
step
is
displayedEntry
's
step
and
targetEntry
's
document state
's
ever populated
is false.
push
Assert
targetEntry
's
step
is
displayedEntry
's
step
+ 1 and
targetEntry
's
document state
's
ever populated
is false.
Let
oldOrigin
be
targetEntry
's
document state
's
origin
If all of the following are true:
navigable
is not
traversable
targetEntry
is not
navigable
's
current session history entry
; and
oldOrigin
is the
same
as
navigable
's
current session history entry
's
document state
's
origin
then:
Let
be
navigable
's
active window
's
navigation API
Fire a traverse
navigate
event
at
given
targetEntry
and
userInvolvement
If
targetEntry
's
document
is null, or
targetEntry
's
document state
's
reload pending
is true, then:
Let
navTimingType
be "
back_forward
" if
targetEntry
's
document
is null; otherwise
reload
".
Let
targetSnapshotParams
be the result of
snapshotting target
snapshot params
given
navigable
Let
potentiallyTargetSpecificSourceSnapshotParams
be
sourceSnapshotParams
If
potentiallyTargetSpecificSourceSnapshotParams
is null, then set it to the
result of
snapshotting source snapshot params
given
navigable
's
active document
In this case there is no clear source of the traversal/reload. We treat this
situation as if
navigable
navigated itself, but note that some properties of
targetEntry
's original initiator are preserved in
targetEntry
's
document state
, such as the
initiator origin
and
referrer
, which will appropriately influence
the navigation.
Set
targetEntry
's
document
state
's
reload pending
to
false.
Let
allowPOST
be
targetEntry
's
document state
's
reload pending
In parallel
attempt to populate the history entry's
document
for
targetEntry
, given
navigable
potentiallyTargetSpecificSourceSnapshotParams
targetSnapshotParams
userInvolvement
, with
allowPOST
set
to
allowPOST
and
completionSteps
set to
queue a global task
on the
navigation and traversal task source
given
navigable
's
active window
to run
afterDocumentPopulated
Otherwise, run
afterDocumentPopulated
immediately
In both cases, let
afterDocumentPopulated
be the following steps:
If
targetEntry
's
document
is null, then
set
changingNavigableContinuation
's
update-only
to true.
This means we tried to populate the document, but were unable to do so,
e.g. because of the server returning a 204.
These kinds of failed navigations or traversals will not be signaled to the
navigation API
(e.g., through the promises of any
navigation API method tracker
, or the
navigateerror
event). Doing so would leak information
about the timing of responses from other origins, in the cross-origin case, and providing
different results in the cross-origin vs. same-origin cases was deemed too confusing.
However, implementations could use this opportunity to clear any promise handlers for
the
navigation.transition.finished
promise, as they are guaranteed at this point to never run. And, they might wish to
report a warning to the console
if any part of the navigation API initiated
these navigations, to make it clear to the web developer why their promises will never
settle and events will never fire.
If
targetEntry
's
document
's
origin
is not
oldOrigin
, then set
targetEntry
's
classic history API
state
to
StructuredSerializeForStorage
(null).
This clears history state when the origin changed vs a previous load of
targetEntry
without a redirect occuring. This can happen due to a change in CSP
sandbox headers.
If all of the following are true:
navigable
's
parent
is null;
targetEntry
's
document
's
browsing context
is not an
auxiliary browsing
context
whose
opener browsing context
is non-null; and
targetEntry
's
document
's
origin
is not
oldOrigin
then set
targetEntry
's
document
state
's
navigable target name
to the empty string.
Enqueue
changingNavigableContinuation
on
changingNavigableContinuations
The rest of this job
runs later
in
this algorithm.
Let
navigablesThatMustWaitBeforeHandlingSyncNavigation
be an empty
set
While
completedChangeJobs
does not equal
totalChangeJobs
If
traversable
's
running
nested apply history step
is false, then:
While
traversable
's
session
history traversal queue
's
algorithm set
contains
one or more
synchronous navigation
steps
with a
target
navigable
not
contained
in
navigablesThatMustWaitBeforeHandlingSyncNavigation
Let
steps
be the first
item
in
traversable
's
session history
traversal queue
's
algorithm set
that
is
synchronous
navigation steps
with a
target
navigable
not
contained
in
navigablesThatMustWaitBeforeHandlingSyncNavigation
Remove
steps
from
traversable
's
session history
traversal queue
's
algorithm
set
Set
traversable
's
running nested apply history step
to
true.
Run
steps
Set
traversable
's
running nested apply history step
to
false.
Synchronous navigations that are intended to take place before this
traversal jump the queue at this point, so they can be added to the correct place in
traversable
's
session history
entries
before this traversal potentially unloads their document.
More details can be found
here
Let
changingNavigableContinuation
be the result
of
dequeuing
from
changingNavigableContinuations
If
changingNavigableContinuation
is nothing, then
continue
Let
displayedDocument
be
changingNavigableContinuation
's
displayed document
Let
targetEntry
be
changingNavigableContinuation
's
target entry
Let
navigable
be
changingNavigableContinuation
's
navigable
Let (
scriptHistoryLength
scriptHistoryIndex
) be the result of
getting the history object length and index
given
traversable
and
targetStep
These values might have changed since they were last calculated.
Append
navigable
to
navigablesThatMustWaitBeforeHandlingSyncNavigation
Once a navigable has reached this point in traversal, additionally queued
synchronous navigation steps are likely to be intended to occur after this traversal rather
than before it, so they no longer jump the queue.
More details can be found here
Let
entriesForNavigationAPI
be the result of
getting session history
entries for the navigation API
given
navigable
and
targetStep
If
changingNavigableContinuation
's
update-only
is true, or
targetEntry
's
document
is
displayedDocument
, then:
This is a same-document navigation: we proceed without unloading.
Set the ongoing navigation
for
navigable
to null.
This allows new
navigations
of
navigable
to start, whereas during the traversal they were blocked.
Queue a global task
on the
navigation and traversal task
source
given
navigable
's
active window
to
perform
afterPotentialUnloads
Otherwise:
Assert
navigationType
is not null.
Deactivate
displayedDocument
, given
userInvolvement
targetEntry
navigationType
, and
afterPotentialUnloads
In both cases, let
afterPotentialUnloads
be the following steps:
Let
previousEntry
be
navigable
's
active session history entry
If
changingNavigableContinuation
's
update-only
is false, then
activate history entry
targetEntry
for
navigable
Let
updateDocument
be an algorithm step which performs
update
document for history step application
given
targetEntry
's
document
targetEntry
changingNavigableContinuation
's
update-only
scriptHistoryLength
scriptHistoryIndex
navigationType
entriesForNavigationAPI
, and
previousEntry
If
targetEntry
's
document
is equal to
displayedDocument
, then perform
updateDocument
Otherwise,
queue a global task
on the
navigation and traversal task
source
given
targetEntry
's
document
's
relevant global object
to perform
updateDocument
Increment
completedChangeJobs
Let
totalNonchangingJobs
be the
size
of
nonchangingNavigablesThatStillNeedUpdates
This step onwards deliberately waits for all the previous operations to
complete, as they include
processing synchronous
navigations
which will also post tasks to update history length and index.
Let
completedNonchangingJobs
be 0.
Let (
scriptHistoryLength
scriptHistoryIndex
) be the result of
getting the history object length and index
given
traversable
and
targetStep
For each
navigable
of
nonchangingNavigablesThatStillNeedUpdates
queue a global task
on the
navigation and traversal task source
given
navigable
's
active window
to run the steps:
Let
document
be
navigable
's
active
document
Set
document
's
history object
's
index
to
scriptHistoryIndex
Set
document
's
history object
's
length
to
scriptHistoryLength
Increment
completedNonchangingJobs
Wait for
completedNonchangingJobs
to equal
totalNonchangingJobs
Set
traversable
's
current
session history step
to
targetStep
Return "
applied
".
To
deactivate a document for a cross-document navigation
given a
Document
displayedDocument
, a
user navigation involvement
userNavigationInvolvement
, a
session history entry
targetEntry
NavigationType
navigationType
, and
afterPotentialUnloads
which is an algorithm that receives no arguments:
Let
navigable
be
displayedDocument
's
node navigable
Let
potentiallyTriggerViewTransition
be false.
Let
isBrowserUINavigation
be true if
userNavigationInvolvement
is "
browser UI
"; otherwise false.
Set
potentiallyTriggerViewTransition
to the result of calling
can navigation trigger a cross-document view-transition?
given
displayedDocument
targetEntry
's
document
navigationType
, and
isBrowserUINavigation
If
potentiallyTriggerViewTransition
is false, then:
Let
firePageSwapBeforeUnload
be the following step:
Fire the
pageswap
event
given
displayedDocument
targetEntry
navigationType
, and
null.
Set the ongoing navigation
for
navigable
to null.
This allows new
navigations
of
navigable
to start, whereas during the traversal they were blocked.
Unload a document and its descendants
given
displayedDocument
targetEntry
's
document
afterPotentialUnloads
, and
firePageSwapBeforeUnload
Otherwise,
queue a global task
on the
navigation and traversal task source
given
navigable
's
active window
to run the steps:
Let
proceedWithNavigationAfterViewTransitionCapture
be the following
step:
Append the following session
history traversal steps
to
navigable
's
traversable navigable
Set the ongoing navigation
for
navigable
to null.
This allows new
navigations
of
navigable
to start, whereas during the traversal they were blocked.
Unload a document and its descendants
given
displayedDocument
targetEntry
's
document
, and
afterPotentialUnloads
Let
viewTransition
be the result of
setting up a cross-document view-transition
given
displayedDocument
targetEntry
's
document
navigationType
, and
proceedWithNavigationAfterViewTransitionCapture
Fire the
pageswap
event
given
displayedDocument
targetEntry
navigationType
, and
viewTransition
If
viewTransition
is null, then run
proceedWithNavigationAfterViewTransitionCapture
In the case where a view transition started, the view transitions
algorithms are responsible for calling
proceedWithNavigationAfterViewTransitionCapture
To
fire the
pageswap
event
given a
Document
displayedDocument
, a
session history entry
targetEntry
, a
NavigationType
navigationType
, and a
ViewTransition
-or-null
viewTransition
Assert
: this is running as part of a
task
queued on
displayedDocument
's
relevant agent
's
event loop
Let
be
displayedDocument
's
relevant global object
's
navigation API
Let
activation
be null.
If all of the following are true:
targetEntry
's
document
's
origin
is
same origin
with
displayedDocument
's
origin
and
targetEntry
's
document
's
was created via cross-origin redirects
is false, or
targetEntry
's
document
's
latest entry
is not null,
then:
Let
destinationEntry
be determined by switching on
navigationType
reload
The
current entry
of
traverse
The
NavigationHistoryEntry
in
's
entry list
whose
session history entry
is
targetEntry
push
replace
A new
NavigationHistoryEntry
in
displayedDocument
's
relevant realm
with its
session history entry
set to
targetEntry
Set
activation
to a
new
NavigationActivation
created in
displayedDocument
's
relevant
realm
, with
old entry
the
current entry
of
new entry
destinationEntry
navigation type
navigationType
This means that a cross-origin redirect during a navigation would result in a
null
activation
in the old document's
PageSwapEvent
, unless the new document is being restored from
bfcache
Fire an event
named
pageswap
at
displayedDocument
's
relevant global object
, using
PageSwapEvent
with its
activation
set to
activation
and its
viewTransition
set to
viewTransition
To
activate history entry
session history entry
entry
for
navigable
navigable
Save persisted state
to the
navigable
's
active session history entry
Let
newDocument
be
entry
's
document
Assert
newDocument
's
is initial
about:blank
is false, i.e., we never traverse back to the
initial
about:blank
Document
because it
always gets
replaced
when we navigate away from
it.
Set
navigable
's
active session history
entry
to
entry
Make active
newDocument
Set the initial visibility state
of
newDocument
to
navigable
's
traversable navigable
's
system visibility state
To
get the used step
given a
traversable
navigable
traversable
, and a non-negative integer
step
, perform the
following steps. They return a non-negative integer.
Let
steps
be the result of
getting all used history steps
within
traversable
Return the greatest
item
in
steps
that is less
than or equal to
step
This caters for situations where there's no
session history entry
with
step
step
, due to the removal of a
navigable
To
get the history object length and
index
given a
traversable navigable
traversable
, and a non-negative
integer
step
, perform the following steps. They return a
tuple
of two
non-negative integers.
Let
steps
be the result of
getting all used history steps
within
traversable
Let
scriptHistoryLength
be the
size
of
steps
Assert
steps
contains
step
It is assumed that
step
has been adjusted by
getting the used
step
Let
scriptHistoryIndex
be the index of
step
in
steps
Return (
scriptHistoryLength
scriptHistoryIndex
).
To
get all navigables whose current session history entry will change or reload
given a
traversable navigable
traversable
, and a non-negative integer
targetStep
, perform the following steps. They return a
list
of
navigables
Let
results
be an empty
list
Let
navigablesToCheck
be «
traversable
».
This list is extended in the loop below.
For each
navigable
of
navigablesToCheck
Let
targetEntry
be the result of
getting the target history
entry
given
navigable
and
targetStep
If
targetEntry
is not
navigable
's
current session history entry
or
targetEntry
's
document state
's
reload pending
is true, then
append
navigable
to
results
If
targetEntry
's
document
is
navigable
's
document
, and
targetEntry
's
document state
's
reload pending
is false, then
extend
navigablesToCheck
with the
child navigables
of
navigable
Adding
child navigables
to
navigablesToCheck
means those navigables will also be checked by this loop.
Child navigables
are only checked if the
navigable
's
active document
will not change as
part of this traversal.
Return
results
To
get
all navigables that only need history object length/index update
given a
traversable
navigable
traversable
, and a non-negative integer
targetStep
perform the following steps. They return a
list
of
navigables
Other
navigables
might not be impacted by the
traversal. For example, if the response is a 204, the currently active document will remain.
Additionally, going 'back' after a 204 will change the
current session history entry
, but the
active session history entry
will already be
correct.
Let
results
be an empty
list
Let
navigablesToCheck
be «
traversable
».
This list is extended in the loop below.
For each
navigable
of
navigablesToCheck
Let
targetEntry
be the result of
getting the target history
entry
given
navigable
and
targetStep
If
targetEntry
is
navigable
's
current session history entry
and
targetEntry
's
document state
's
reload pending
is false, then:
Append
navigable
to
results
Extend
navigablesToCheck
with
navigable
's
child navigables
Adding
child navigables
to
navigablesToCheck
means those navigables will also be checked by this loop.
child navigables
are only checked if the
navigable
's
active document
will not change
as part of this traversal.
Return
results
To
get the target history entry
given a
navigable
navigable
, and a non-negative integer
step
, perform
the following steps. They return a
session history entry
Let
entries
be the result of
getting session history entries
for
navigable
Return the
item
in
entries
that has the
greatest
step
less than or equal to
step
To see why
getting the target history entry
returns the entry with the greatest
step
less than or equal to the input step, consider the following
Jake diagram
top
/t
/t#foo
frames[0]
/i-0-a
/i-0-b
For the input step 1, the target history entry for the
top
navigable
is the
/t
entry, whose
step
is 0, while the target history entry for the
frames[0]
navigable is the
/i-0-b
entry, whose
step
is 1:
top
/t
/t#foo
frames[0]
/i-0-a
/i-0-b
Similarly, given the input step 3 we get the
top
entry whose
step
is 3, and the
frames[0]
entry whose
step
is 1:
top
/t
/t#foo
frames[0]
/i-0-a
/i-0-b
To
get
all navigables that might experience a cross-document traversal
given a
traversable
navigable
traversable
, and a non-negative integer
targetStep
perform the following steps. They return a
list
of
navigables
From
traversable
's
session
history traversal queue
's perspective, these documents are candidates for going
cross-document during the traversal described by
targetStep
. They will not experience
a cross-document traversal if the status code for their target document is HTTP 204 No Content.
Note that if a given
navigable
might experience a cross-document traversal, this
algorithm will return
navigable
but not its
child
navigables
. Those would end up
unloaded
, not
traversed.
Let
results
be an empty
list
Let
navigablesToCheck
be «
traversable
».
This list is extended in the loop below.
For each
navigable
of
navigablesToCheck
Let
targetEntry
be the result of
getting the target history
entry
given
navigable
and
targetStep
If
targetEntry
's
document
is not
navigable
's
document
or
targetEntry
's
document state
's
reload pending
is true, then
append
navigable
to
results
Although
navigable
's
active history entry
can change synchronously, the
new entry will always have the same
Document
, so accessing
navigable
's
document
is reliable.
Otherwise,
extend
navigablesToCheck
with
navigable
's
child navigables
Adding
child navigables
to
navigablesToCheck
means those navigables will also be checked by this loop.
Child navigables
are only checked if the
navigable
's
active document
will not change as
part of this traversal.
Return
results
7.4.6.2
Updating the document
To
update document for history step application
given a
Document
document
, a
session history entry
entry
, a boolean
doNotReactivate
, integers
scriptHistoryLength
and
scriptHistoryIndex
NavigationType
-or-null
navigationType
, an
optional
list
of
session history entries
entriesForNavigationAPI
, and an optional
session history entry
previousEntryForActivation
Let
documentIsNew
be true if
document
's
latest entry
is null; otherwise false.
Let
documentsEntryChanged
be true if
document
's
latest
entry
is not
entry
; otherwise false.
Set
document
's
history object
's
index
to
scriptHistoryIndex
Set
document
's
history object
's
length
to
scriptHistoryLength
Let
be
history
's
relevant global object
's
navigation API
If
documentsEntryChanged
is true, then:
Let
oldURL
be
document
's
latest entry
's
URL
Set
document
's
latest entry
to
entry
Restore the history object state
given
document
and
entry
If
documentIsNew
is false, then:
Assert
navigationType
is not null.
Update the navigation API entries for a same-document navigation
given
entry
, and
navigationType
Fire an event
named
popstate
at
document
's
relevant global
object
, using
PopStateEvent
, with the
state
attribute initialized to
document
's
history object
's
state
and
hasUAVisualTransition
initialized to
true if a visual transition, to display a cached rendered state of the
latest
entry
, was done by the user agent.
Restore persisted state
given
entry
If
oldURL
's
fragment
is not
equal to
entry
's
URL
's
fragment
, then
queue a global task
on the
DOM manipulation task source
given
document
's
relevant global
object
to
fire an event
named
hashchange
at
document
's
relevant global
object
, using
HashChangeEvent
, with the
oldURL
attribute initialized to the
serialization
of
oldURL
and the
newURL
attribute initialized to the
serialization
of
entry
's
URL
Otherwise:
Assert
entriesForNavigationAPI
is given.
Restore persisted state
given
entry
Initialize the navigation API entries for a new document
given
entriesForNavigationAPI
, and
entry
If all the following are true:
previousEntryForActivation
is given;
navigationType
is non-null; and
navigationType
is "
reload
" or
previousEntryForActivation
's
document
is not
document
then:
If
's
activation
is null, then set
's
activation
to a new
NavigationActivation
object in
's
relevant realm
Let
previousEntryIndex
be the result of
getting the navigation API entry index
of
previousEntryForActivation
within
If
previousEntryIndex
is non-negative, then set
activation
's
old entry
to
's
entry list
previousEntryIndex
].
Otherwise, if all the following are true:
navigationType
is "
replace
";
previousEntryForActivation
's
document state
's
origin
is
same origin
with
document
's
origin
; and
previousEntryForActivation
's
document
's
initial
about:blank
is
false,
then set
activation
's
old entry
to a new
NavigationHistoryEntry
in
's
relevant realm
, whose
session history entry
is
previousEntryForActivation
Set
activation
's
new entry
to
's
current entry
Set
activation
's
navigation type
to
navigationType
If
documentIsNew
is true, then:
Assert
document
's
during-loading navigation ID for WebDriver BiDi
is not null.
Invoke
WebDriver BiDi navigation committed
with
navigable
and a
new
WebDriver BiDi navigation status
whose
id
is
document
's
during-loading navigation ID for WebDriver BiDi
status
is "
committed
", and
url
is
document
's
URL
Try to scroll to the fragment
for
document
At this point
scripts may run for the newly-created document
document
Otherwise, if
documentsEntryChanged
is false and
doNotReactivate
is
false, then:
Assert
entriesForNavigationAPI
is given.
Reactivate
document
given
entry
and
entriesForNavigationAPI
documentsEntryChanged
can be false for one of two reasons: either we
are restoring from
bfcache
, or we are asynchronously finishing up a
synchronous navigation which already synchronously set
document
's
latest
entry
. The
doNotReactivate
argument distinguishes between these two
cases.
To
restore the history object state
given
Document
document
and
session history entry
entry
Let
targetRealm
be
document
's
relevant realm
Let
state
be
StructuredDeserialize
entry
's
classic history API state
targetRealm
).
If this throws an exception, catch it and let
state
be null.
Set
document
's
history object
's
state
to
state
To
make active
Document
document
Let
window
be
document
's
relevant global
object
Set
document
's
browsing context
's
WindowProxy
's
[[Window]]
internal
slot value to
window
Set
window
's
relevant settings object
's
execution ready flag
To
reactivate
Document
document
given a
session history entry
reactivatedEntry
and a
list
of
session history entries
entriesForNavigationAPI
This algorithm updates
document
after it has come out of
bfcache
, i.e., after it has been made
fully active
again. Other specifications that want to watch for this change to the
fully
active
state are encouraged to add steps into this algorithm, so that the ordering
of events that happen in effect of the change is clear.
For each
formControl
of form controls in
document
with an
autofill field
name
of "
off
", invoke the
reset algorithm
for
formControl
If
document
's
suspended timer handles
is not
empty
Assert
document
's
suspension time
is not
zero.
Let
suspendDuration
be the
current high resolution time
minus
document
's
suspension time
Let
activeTimers
be
document
's
relevant global
object
's
map of active timers
For each
handle
in
document
's
suspended timer
handles
, if
activeTimers
handle
exists
, then increase
activeTimers
handle
] by
suspendDuration
Update the navigation API entries for reactivation
given
document
's
relevant global object
's
navigation API
entriesForNavigationAPI
, and
reactivatedEntry
If
document
's
current document readiness
is "
complete
", and
document
's
page showing
is false:
Set
document
's
page showing
to true.
Set
document
's
has been revealed
to false.
Update the visibility state
of
document
to "
visible
".
Fire a page transition event
named
pageshow
at
document
's
relevant global
object
with true.
To
try to scroll to the fragment
for a
Document
document
perform the following steps
in parallel
Wait for an
implementation-defined
amount of time. (This is intended to allow
the user agent to optimize the user experience in the face of performance concerns.)
Queue a global task
on the
navigation and traversal task source
given
document
's
relevant global object
to run these steps:
If
document
has no parser, or its parser has
stopped parsing
, or the user agent has reason to believe the user is no longer
interested in scrolling to the
fragment
, then abort
these steps.
Scroll to the fragment
given
document
If
document
's
indicated part
is still null, then
try to
scroll to the fragment
for
document
To
make document unsalvageable
, given a
Document
document
and a string
reason
Let
details
be a new
not restored reason details
whose
reason
is
reason
Append
details
to
document
's
bfcache blocking details
Set
document
's
salvageable
state to false.
To
build not restored reasons for document state
given
Document
document
Let
notRestoredReasonsForDocument
be a new
not restored reasons
Set
notRestoredReasonsForDocument
's
URL
to
document
's
URL
Let
container
be
document
's
node navigable
's
container
If
container
is an
iframe
element:
Let
src
be the empty string.
If
container
has a
src
attribute:
Let
src
be the result of
encoding-parsing-and-serializing a
URL
given
container
's
src
attribute's
value, relative to
container
's
node document
If
src
is failure, then set
src
to
container
's
src
attribute's value.
Set
notRestoredReasonsForDocument
's
src
to
src
Set
notRestoredReasonsForDocument
's
id
to
container
's
id
attribute's value, or the empty string
if it has no such attribute.
Set
notRestoredReasonsForDocument
's
name
to
container
's
name
attribute's value, or the
empty string if it has no such attribute.
Set
notRestoredReasonsForDocument
's
reasons
to a
clone
of
document
's
bfcache blocking details
For each
navigable
of
document
's
document-tree child navigables
Let
childDocument
be
navigable
's
active document
Build not restored reasons for document state
given
childDocument
Append
childDocument
's
not restored reasons
to
notRestoredReasonsForDocument
's
children
Set
document
's
node navigable
's
active session history entry
's
document state
's
not restored reasons
to
notRestoredReasonsForDocument
To
build not restored reasons for a top-level traversable and its descendants
given
top-level traversable
topLevelTraversable
Build not restored reasons for document state
given
topLevelTraversable
's
active document
Let
crossOriginDescendants
be an empty
list
For each
childNavigable
of
topLevelTraversable
's
active document
's
descendant navigables
If
childNavigable
's
active document
's
origin
is not
same origin
with
topLevelTraversable
's
active document
's
origin
, then
append
childNavigable
to
crossOriginDescendants
Let
crossOriginDescendantsPreventsBfcache
be false.
For each
crossOriginNavigable
of
crossOriginDescendants
Let
reasonsForCrossOriginChild
be
crossOriginNavigable
's
active document
's
document state
's
not restored reasons
If
reasonsForCrossOriginChild
's
reasons
is not empty, set
crossOriginDescendantsPreventsBfcache
to true.
Set
reasonsForCrossOriginChild
's
URL
to
null.
Set
reasonsForCrossOriginChild
's
reasons
to null.
Set
reasonsForCrossOriginChild
's
children
to null.
If
crossOriginDescendantsPreventsBfcache
is true,
make document
unsalvageable
given
topLevelTraversable
's
active document
and "
masked
".
7.4.6.3
Revealing the document
Document
has a boolean
has been revealed
, initially false. It is used
to ensure that the
pagereveal
event is fired once for each
activation of the
Document
(once when it's rendered initially, and once for each
reactivation
).
To
reveal
Document
document
If
document
's
has been revealed
is true, then return.
Set
document
's
has been revealed
to true.
Let
transition
be the result of
resolving inbound cross-document view-transition
for
document
Fire an event
named
pagereveal
at
document
's
relevant global object
, using
PageRevealEvent
with its
viewTransition
set to
transition
If
transition
is not null, then:
Prepare to run script
given
document
's
relevant settings object
Activate
transition
Clean up after running script
given
document
's
relevant settings object
Activating a view transition might resolve/reject promises, so by wrapping the
activation with prepare/cleanup we ensure those promises are handled before the next rendering
step.
Though
pagereveal
is guaranteed to be fired
during the first
update the rendering
step that displays an up-to-date version of the
page, user agents are free to display a cached frame of the page before firing it. This prevents
the presence of a
pagereveal
handler from delaying the
presentation of such cached frame.
7.4.6.4
Scrolling to a fragment
To
scroll to the fragment
given a
Document
document
If
document
's
indicated part
is null, then set
document
's
target element
to null.
Otherwise, if
document
's
indicated part
is
top of the
document
, then:
Set
document
's
target element
to null.
Scroll to the beginning of the document
for
document
[CSSOMVIEW]
Return.
Otherwise:
Assert
document
's
indicated part
is an
element.
Let
target
be
document
's
indicated part
Set
document
's
target element
to
target
Run the
ancestor revealing algorithm
on
target
Scroll
target
into view
with
behavior
set to "auto",
block
set to "start", and
inline
set to "nearest".
[CSSOMVIEW]
Run the
focusing steps
for
target
, with the
Document
's
viewport
as the
fallback target
Move the
sequential focus navigation starting point
to
target
Document
's
indicated part
is
the one that its
URL
's
fragment
identifies, or null if the fragment does not
identify anything. The semantics of the
fragment
in
terms of mapping it to a node is defined by the specification that defines the
MIME
type
used by the
Document
(for example, the processing of
fragments
for
XML MIME
types
is the responsibility of RFC7303).
[RFC7303]
There is also a
target element
for each
Document
, which is used in
defining the
:target
pseudo-class and is updated by the
above algorithm. It is initially null.
For an
HTML document
document
, its
indicated part
is the result
of
selecting the indicated part
given
document
and
document
's
URL
To
select the indicated part
given a
Document
document
and a
URL
url
If
document
's
URL
does not
equal
url
with
exclude fragments
set to
true, then return null.
Let
fragment
be
url
's
fragment
If
fragment
is the empty string, then return the special value
top of the
document
Let
potentialIndicatedElement
be the result of
finding a potential indicated element
given
document
and
fragment
If
potentialIndicatedElement
is not null, then return
potentialIndicatedElement
Let
fragmentBytes
be the result of
percent-decoding
fragment
Let
decodedFragment
be the result of running
UTF-8 decode without
BOM
on
fragmentBytes
Set
potentialIndicatedElement
to the result of
finding a potential indicated element
given
document
and
decodedFragment
If
potentialIndicatedElement
is not null, then return
potentialIndicatedElement
If
decodedFragment
is an
ASCII case-insensitive
match for the
string
top
, then return the
top of the document
Return null.
To
find a potential indicated element
given a
Document
document
and a string
fragment
, run these steps:
If there is an element
in the document tree
whose
root
is
document
and that has an
ID
equal to
fragment
, then return the first such element
in
tree order
If there is an
element
in the document
tree
whose
root
is
document
that has a
name
attribute whose value is equal to
fragment
, then
return the first such element in
tree order
Return null.
7.4.6.5
Persisted history entry state
To
save persisted state
to a
session history entry
entry
Set the
scroll position data
of
entry
to contain the scroll positions for all of
entry
's
document
's
restorable scrollable regions
Optionally, update
entry
's
persisted user state
to reflect any state that the user agent wishes to persist, such as the values of form
fields.
To
restore persisted state
from a
session
history entry
entry
If
entry
's
scroll restoration
mode
is "
auto
", and
entry
's
document
's
relevant global object
's
navigation API
's
suppress normal scroll restoration
during ongoing navigation
is false, then
restore scroll position data
given
entry
The user agent not restoring scroll positions does not imply that scroll
positions will be left at any particular value (e.g., (0,0)). The actual scroll position depends
on the navigation type and the user agent's particular caching strategy. So web applications
cannot assume any particular scroll position but rather are urged to set it to what they want it
to be.
If
suppress normal scroll restoration during ongoing navigation
is
true, then
restoring scroll position data
might still happen at a later point, as part of
finishing
the relevant
NavigateEvent
, or via a
navigateEvent.scroll()
method call.
Optionally, update other aspects of
entry
's
document
and its rendering, for instance values of form fields,
that the user agent had previously recorded in
entry
's
persisted user state
This can even include updating the
dir
attribute
of
textarea
elements or
input
elements whose
type
attribute is in the
Text
Telephone
URL
, or
Email
state, if the persisted state includes the directionality of user input in such controls.
Restoring the value of form controls as part of this process does not fire any
input
or
change
events, but
can trigger the
formStateRestoreCallback
of
form-associated custom elements
Each
Document
has a boolean
has been scrolled by the user
, initially
false. If the user scrolls the document, the user agent must set that document's
has been
scrolled by the user
to true.
The
restorable scrollable regions
of a
Document
document
are
document
's
viewport
, and all of
document
's scrollable
regions excepting any
navigable containers
Child navigable
scroll restoration is handled as part of state
restoration for the
session history entry
for those
navigables
Document
s.
To
restore scroll position data
given a
session history entry
entry
Let
document
be
entry
's
document
If
document
's
has been scrolled by the user
is true, then the
user agent should return.
The user agent should attempt to use
entry
's
scroll position data
to restore the scroll positions of
entry
's
document
's
restorable scrollable
regions
. The user agent may continue to attempt to do so periodically, until
document
's
has been scrolled by the user
becomes true.
This is formulated as an
attempt
, which is potentially repeated until
success or until the user scrolls, due to the fact that relevant content indicated by the
scroll position data
might take some time to load from the
network.
Scroll restoration might be affected by scroll anchoring.
[CSSSCROLLANCHORING]
US