The inner navigate event firing algorithm consists of the following steps, given a Navigation navigation, a NavigationType navigationType, a NavigateEvent event, a NavigationDestination destination, a user navigation involvement userInvolvement, an Element-or-null sourceElement, an entry list-or-null formDataEntryList, a string-or-null downloadRequestFilename, and an optional navigation API method tracker-or-null apiMethodTracker (default null):

  1. If navigation has entries and events disabled:

    1. Assert: navigation's ongoing API method tracker is null.

    2. Assert: navigation's upcoming traverse API method trackers is empty.

    3. Assert: apiMethodTracker is null.

    4. Return true.

    These assertions holds because traverseTo(), back(), and forward() will immediately fail when entries and events are disabled (since there are no entries to traverse to).

  2. Assert: navigation's ongoing API method tracker is null.

  3. If destination's entry is non-null:

    1. Assert: apiMethodTracker is null.

      apiMethodTracker is passed as an argument only for navigate() and reload() calls.

    2. Let destinationKey be destination's entry's key.

    3. Assert: destinationKey is not the empty string.

    4. If navigation's upcoming traverse API method trackers[destinationKey] exists:

      1. Set apiMethodTracker to navigation's upcoming traverse API method trackers[destinationKey].

      2. Remove navigation's upcoming traverse API method trackers[destinationKey].

  4. If apiMethodTracker is not null:

    1. Set navigation's ongoing API method tracker to apiMethodTracker.

    2. Set apiMethodTracker's pending to false.

  5. Let navigable be navigation's relevant global object's navigable.

  6. Let document be navigation's relevant global object's associated Document.

  7. If document can have its URL rewritten to destination's URL, and either destination's is same document is true or navigationType is not "traverse", then initialize event's canIntercept to true. Otherwise, initialize it to false.

  8. If either:

    • navigationType is not "traverse"; or

    • traverseCanBeCanceled is true,

    then initialize event's cancelable to true. Otherwise, initialize it to false.

  9. Initialize event's type to "navigate".

  10. Initialize event's navigationType to navigationType.

  11. Initialize event's destination to destination.

  12. Initialize event's downloadRequest to downloadRequestFilename.

  13. If apiMethodTracker is not null, then initialize event's info to apiMethodTracker's info. Otherwise, initialize it to undefined.

    At this point apiMethodTracker's info is no longer needed and can be nulled out instead of keeping it alive for the lifetime of the navigation API method tracker.

  14. Initialize event's hasUAVisualTransition to true if a visual transition, to display a cached rendered state of the document's latest entry, was done by the user agent. Otherwise, initialize it to false.

  15. Initialize event's sourceElement to sourceElement.

  16. Set event's abort controller to a new AbortController created in navigation's relevant realm.

  17. Initialize event's signal to event's abort controller's signal.

  18. Let currentURL be document's URL.

  19. If all of the following are true:

    then initialize event's hashChange to true. Otherwise, initialize it to false.

    The first condition here means that hashChange will be true for fragment navigations, but false for cases like history.pushState(undefined, "", "#fragment").

  20. If userInvolvement is not "none", then initialize event's userInitiated to true. Otherwise, initialize it to false.

  21. If formDataEntryList is not null, then initialize event's formData to a new FormData created in navigation's relevant realm, associated to formDataEntryList. Otherwise, initialize it to null.

  22. Assert: navigation's ongoing navigate event is null.

  23. Set navigation's ongoing navigate event to event.

  24. Set navigation's focus changed during ongoing navigation to false.

  25. Set navigation's suppress normal scroll restoration during ongoing navigation to false.

  26. Let dispatchResult be the result of dispatching event at navigation.

  27. If dispatchResult is false:

    1. If navigationType is "traverse", then consume history-action user activation given navigation's relevant global object.

    2. If event's abort controller's signal is not aborted, then abort the ongoing navigation given navigation.

    3. Return false.

  28. If event's interception state is not "none":

    1. Let fromNHE be the current entry of navigation.

    2. Assert: fromNHE is not null.

    3. Set navigation's transition to a new NavigationTransition created in navigation's relevant realm, with

      navigation type
      navigationType
      from entry
      fromNHE
      destination
      event's destination
      committed promise
      a new promise created in navigation's relevant realm
      finished promise
      a new promise created in navigation's relevant realm
    4. Mark as handled navigation's transition's finished promise.

      See the discussion about other finished promises to understand why this is done.

    5. Mark as handled navigation's transition's committed promise.

  29. If event's navigation precommit handler list is empty then commit event given apiMethodTracker.

  30. Otherwise:

    1. Let precommitController be a new NavigationPrecommitController created in navigation's relevant realm, whose event is event.

    2. Let precommitPromisesList be an empty list.

    3. For each handler of event's navigation precommit handler list:

      1. Append the result of invoking handler with « precommitController » to precommitPromisesList.

    4. Wait for all precommitPromisesList with the following success steps: commit event given apiMethodTracker, and the following failure step given reason: process navigate event handler failure given event and reason.

  31. If event's interception state is "none", then return true.

  32. Return false.