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):
If navigation has entries and events disabled:
Assert: navigation's ongoing API method tracker is null.
Assert: navigation's upcoming traverse API method trackers is empty.
Assert: apiMethodTracker is null.
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).
Assert: navigation's ongoing API method tracker is null.
If destination's entry is non-null:
Assert: apiMethodTracker is null.
apiMethodTracker is passed as an argument only for navigate() and reload() calls.
Assert: destinationKey is not the empty string.
If navigation's upcoming traverse API method trackers[destinationKey] exists:
Set apiMethodTracker to navigation's upcoming traverse API method trackers[destinationKey].
Remove navigation's upcoming traverse API method trackers[destinationKey].
If apiMethodTracker is not null:
Set navigation's ongoing API method tracker to apiMethodTracker.
Set apiMethodTracker's pending to false.
Let navigable be navigation's relevant global object's navigable.
Let document be navigation's relevant global object's
associated Document.
If document can have its URL rewritten to destination's
URL, and either destination's
is same document is true or
navigationType is not "traverse",
then initialize event's canIntercept to true. Otherwise, initialize it to
false.
Let traverseCanBeCanceled be true if all of the following are true:
navigable is a top-level traversable;
destination's is same document is true; and
either userInvolvement is not "browser
UI", or navigation's relevant global object has
history-action activation.
Otherwise, let it be false.
If either:
navigationType is not "traverse"; or
traverseCanBeCanceled is true,
then initialize event's cancelable to
true. Otherwise, initialize it to false.
Initialize event's navigationType to
navigationType.
Initialize event's destination to destination.
Initialize event's downloadRequest to
downloadRequestFilename.
If apiMethodTracker is not null, then initialize event's info to apiMethodTracker's info. Otherwise, initialize it to
undefined.
At this point apiMethodTracker's info is no longer needed and can be nulled out instead of keeping it alive for the lifetime of the navigation API method tracker.
Initialize event's 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.
Initialize event's sourceElement to
sourceElement.
Set event's abort
controller to a new AbortController created in
navigation's relevant realm.
Initialize event's signal to
event's abort
controller's signal.
Let currentURL be document's URL.
If all of the following are true:
event's classic history API state is null;
destination's is same document is true;
destination's URL equals currentURL with exclude fragments set to true; and
destination's URL's fragment is not identical to currentURL's fragment,
then initialize event's hashChange to true. Otherwise, initialize it to
false.
The first condition here means that hashChange will be true for fragment navigations, but false for cases like history.pushState(undefined, "", "#fragment").
If userInvolvement is not "none", then
initialize event's userInitiated
to true. Otherwise, initialize it to false.
If formDataEntryList is not null, then initialize event's formData to a new FormData
created in navigation's relevant realm,
associated to formDataEntryList. Otherwise, initialize it to null.
Assert: navigation's ongoing navigate event is null.
Set navigation's ongoing navigate
event to event.
Set navigation's focus changed during ongoing navigation to false.
Set navigation's suppress normal scroll restoration during ongoing navigation to false.
Let dispatchResult be the result of dispatching event at navigation.
If dispatchResult is false:
If navigationType is "traverse", then consume history-action user
activation given navigation's relevant global object.
If event's abort controller's signal is not aborted, then abort the ongoing navigation given navigation.
Return false.
If event's interception
state is not "none":
Let fromNHE be the current entry of navigation.
Assert: fromNHE is not null.
Set navigation's transition
to a new NavigationTransition created in navigation's
relevant realm, with
destinationMark as handled navigation's transition's finished promise.
See the discussion about other finished promises to understand why this is done.
Mark as handled navigation's transition's committed promise.
If event's navigation precommit handler list is empty then commit event given apiMethodTracker.
Otherwise:
Let precommitController be a new NavigationPrecommitController
created in navigation's relevant realm,
whose event is
event.
Let precommitPromisesList be an empty list.
For each handler of event's navigation precommit handler list:
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.
If event's interception
state is "none", then return true.
Return false.