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".

  1. Assert: This is running within traversable's session history traversal queue.

  2. Let targetStep be the result of getting the used step given traversable and step.

  3. If initiatorToCheck is not null:

    1. Assert: sourceSnapshotParams is not null.

    2. 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".

  4. Let navigablesCrossingDocuments be the result of getting all navigables that might experience a cross-document traversal given traversable and targetStep.

  5. 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.

  6. Let changingNavigables be the result of get all navigables whose current session history entry will change or reload given traversable and targetStep.

  7. Let nonchangingNavigablesThatStillNeedUpdates be the result of getting all navigables that only need history object length/index update given traversable and targetStep.

  8. For each navigable of changingNavigables:

    1. Let targetEntry be the result of getting the target history entry given navigable and targetStep.

    2. Set navigable's current session history entry to targetEntry.

    3. 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:

      1. Let navigation be navigable's active window's navigation API.

      2. Set navigation's ongoing navigate event to null.

      3. 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.

    4. Set navigable's ongoing navigation to "traversal".

  9. Let totalChangeJobs be the size of changingNavigables.

  10. Let completedChangeJobs be 0.

  11. 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.

  12. 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.

    1. Let displayedEntry be navigable's active session history entry.

    2. Let targetEntry be navigable's current session history entry.

    3. Let changingNavigableContinuation be a changing navigable continuation state with:

      displayed document
      displayedEntry's document
      target entry
      targetEntry
      navigable
      navigable
      update-only
      false
    4. If displayedEntry is targetEntry and targetEntry's document state's reload pending is false:

      1. Set changingNavigableContinuation's update-only to true.

      2. Enqueue changingNavigableContinuation on changingNavigableContinuations.

      3. Abort these steps.

      This case occurs due to a synchronous navigation which already updated the active session history entry.

    5. 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.

    6. Let oldOrigin be targetEntry's document state's origin.

    7. If all of the following are true:

      then:

      1. Let navigation be navigable's active window's navigation API.

      2. Fire a traverse navigate event at navigation given targetEntry and userInvolvement.

    8. If targetEntry's document is null, or targetEntry's document state's reload pending is true:

      1. Let navTimingType be "back_forward" if targetEntry's document is null; otherwise "reload".

      2. Let targetSnapshotParams be the result of snapshotting target snapshot params given navigable.

      3. Let potentiallyTargetSpecificSourceSnapshotParams be sourceSnapshotParams.

      4. 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.

      5. Set targetEntry's document state's reload pending to false.

      6. Let allowPOST be targetEntry's document state's reload pending.

      7. 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:

      1. 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.

      2. 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.

      3. If all of the following are true:

        then set targetEntry's document state's navigable target name to the empty string.

      4. Enqueue changingNavigableContinuation on changingNavigableContinuations.

        The rest of this job runs later in this algorithm.

  13. Let navigablesThatMustWaitBeforeHandlingSyncNavigation be an empty set.

  14. While completedChangeJobs does not equal totalChangeJobs:

    1. If traversable's running nested apply history step is false:

      1. 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:

        1. 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.

        2. Remove steps from traversable's session history traversal queue's algorithm set.

        3. Set traversable's running nested apply history step to true.

        4. Run steps.

        5. 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.

    2. Let changingNavigableContinuation be the result of dequeuing from changingNavigableContinuations.

    3. If changingNavigableContinuation is nothing, then continue.

    4. Let displayedDocument be changingNavigableContinuation's displayed document.

    5. Let targetEntry be changingNavigableContinuation's target entry.

    6. Let navigable be changingNavigableContinuation's navigable.

    7. 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.

    8. 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.

    9. Let entriesForNavigationAPI be the result of getting session history entries for the navigation API given navigable and targetStep.

    10. If changingNavigableContinuation's update-only is true, or targetEntry's document is displayedDocument:

      This is a same-document navigation: we proceed without unloading.

      1. Set navigable's ongoing navigation to null.

        This allows new navigations of navigable to start, whereas during the traversal they were blocked.

      2. Queue a global task on the navigation and traversal task source given navigable's active window to perform afterPotentialUnloads.

    11. Otherwise:

      1. Assert: navigationType is not null.

      2. Deactivate displayedDocument, given userInvolvement, targetEntry, navigationType, and afterPotentialUnloads.

    12. In both cases, let afterPotentialUnloads be the following steps:

      1. Let previousEntry be navigable's active session history entry.

      2. If changingNavigableContinuation's update-only is false, then activate history entry targetEntry for navigable.

      3. 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.

      4. If targetEntry's document is equal to displayedDocument, then perform updateDocument.

      5. Otherwise, queue a global task on the navigation and traversal task source given targetEntry's document's relevant global object to perform updateDocument.

      6. Increment completedChangeJobs.

  15. 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.

  16. Let completedNonchangingJobs be 0.

  17. Let (scriptHistoryLength, scriptHistoryIndex) be the result of getting the history object length and index given traversable and targetStep.

  18. 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:

    1. Let document be navigable's active document.

    2. Set document's history object's index to scriptHistoryIndex.

    3. Set document's history object's length to scriptHistoryLength.

    4. Increment completedNonchangingJobs.

  19. Wait for completedNonchangingJobs to equal totalNonchangingJobs.

  20. Set traversable's current session history step to targetStep.

  21. Return "applied".