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:
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.
If targetEntry's document is not navigable's active document, then queue a global task on the navigation and traversal task source of navigable's active window to run these steps:
Let navigation be navigable's active window's navigation API.
Set navigation's ongoing navigate event to null.
Set navigation's ongoing API method tracker to null.
This prevents the navigateerror
event and the corresponding signal from firing
as a result of a successful cross-document navigation.
Set navigable's ongoing navigation 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:
If displayedEntry is targetEntry and targetEntry's document state's reload pending is false:
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 navigation be navigable's active window's navigation API.
Fire a traverse navigate event at
navigation given targetEntry and userInvolvement.
If targetEntry's document is null, or targetEntry's document state's reload pending is true:
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
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:
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:
This is a same-document navigation: we proceed without unloading.
Set navigable's ongoing navigation 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".