Skip to content

Commit

Permalink
Consolidate ongoing navigation signal tracking
Browse files Browse the repository at this point in the history
Follows https://chromium-review.googlesource.com/c/chromium/src/+/3102875, although it's not clear that the "inform app history about canceling navigation" / "inform app history about canceling traversals" is quite right since the implementation is a bit different from the spec and per whatwg/html#6927 browsers are quite messy.
  • Loading branch information
domenic committed Aug 18, 2021
1 parent f647fa4 commit 90e9f72
Showing 1 changed file with 10 additions and 12 deletions.
22 changes: 10 additions & 12 deletions spec.bs
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ We end up accomplishing all this using the following setup:

Each {{AppHistory}} object has an associated <dfn for="AppHistory">ongoing navigate event</dfn>, an {{AppHistoryNavigateEvent}} or null, initially null.

Each {{AppHistory}} object has an associated <dfn for="AppHistory">post-navigate event ongoing navigation signal</dfn>, which is an {{AbortSignal}} or null, initially null.
Each {{AppHistory}} object has an associated <dfn for="AppHistory">ongoing navigation signal</dfn>, which is an {{AbortSignal}} or null, initially null.

Each {{AppHistory}} object has an associated <dfn for="AppHistory">upcoming non-traverse navigation</dfn>, which is an [=app history API navigation=] or null, initially null.

Expand All @@ -547,7 +547,7 @@ An <dfn>app history API navigation</dfn> is a [=struct=] with the following [=st
* A <dfn for="app history API navigation">returned promise</dfn>, a {{Promise}}
* A <dfn for="app history API navigation">cleanup step</dfn>, an algorithm step

<p class="note">We need to store the {{AbortSignal}} separately from the [=app history API navigation=] struct, since it needs to be tracked even for navigations that are not via the app history APIs. So, we store it some of the time in the [=AppHistory/ongoing navigate event=]'s {{AppHistoryNavigateEvent/signal}} property, and the rest of the time in the [=AppHistory/post-navigate event ongoing navigation signal=].
<p class="note">We need to store the [=AppHistory/ongoing navigation signal=] separately from the [=app history API navigation=] struct, since it needs to be tracked even for navigations that are not via the app history APIs.

<div algorithm>
To <dfn for="AppHistory">set the upcoming non-traverse navigation</dfn> given an {{AppHistory}} |appHistory|, a JavaScript value |info|, and a [=serialized state=]-or-null |serializedState|:
Expand Down Expand Up @@ -1131,12 +1131,11 @@ The <dfn attribute for="AppHistoryDestination">sameDocument</dfn> getter steps a
1. If |formDataEntryList| is not null, then initialize |event|'s {{AppHistoryNavigateEvent/formData}} to a [=new=] {{FormData}} created in |appHistory|'s [=relevant Realm=], associated to |formDataEntryList|. Otherwise, initialize it to null.
1. [=Assert=]: |appHistory|'s [=AppHistory/ongoing navigate event=] is null.
1. Set |appHistory|'s [=AppHistory/ongoing navigate event=] to |event|.
1. [=Assert=]: |appHistory|'s [=AppHistory/ongoing navigation signal=] is null.
1. Set |appHistory|'s [=AppHistory/ongoing navigation signal=] to |event|'s {{AppHistoryNavigateEvent/signal}}.
1. Let |dispatchResult| be the result of [=dispatching=] |event| at |appHistory|.
1. Let |shouldContinue| be |dispatchResult|.
1. Set |appHistory|'s [=AppHistory/ongoing navigate event=] to null.
1. If |event|'s {{AppHistoryNavigateEvent/signal}}'s [=AbortSignal/aborted flag=] is set, then return false.
<p class="note">This can occur if an event listener performed an action that triggers [=inform app history about canceling navigation=], such as disconnecting a containing <{iframe}> or starting another navigation.
1. Set |appHistory|'s [=AppHistory/post-navigate event ongoing navigation signal=] to |event|'s {{AppHistoryNavigateEvent/signal}}.
1. If |dispatchResult| is true:
1. Assert: |appHistory|'s [=AppHistory/current index=] is not &minus;1.
1. Let |fromEntry| be |appHistory|'s [=AppHistory/entry list=][|appHistory|'s [=AppHistory/current index=]].
Expand Down Expand Up @@ -1166,22 +1165,20 @@ The <dfn attribute for="AppHistoryDestination">sameDocument</dfn> getter steps a
<p class="note">If |event|'s [=AppHistoryNavigateEvent/navigation action promises list=] is non-empty, then {{AppHistoryNavigateEvent/transitionWhile()}} was called and so we're performing a same-document navigation, for which we want to fire {{AppHistory/navigatesuccess}} or {{AppHistory/navigateerror}} events, and resolve or reject the promise returned by the corresponding {{AppHistory/navigate()|appHistory.navigate()}} call if one exists. Otherwise, if the navigation is same-document and was not canceled, we still perform these actions after a microtask (by waiting for zero promises), or after the appropriate task in the traversal case.
1. Otherwise, if |ongoingNavigation| is non-null, then set |ongoingNavigation|'s [=app history API navigation/serialized state=] to null.
<p class="note">This ensures that any call to {{AppHistory/navigate()|appHistory.navigate()}} which triggered this algorithm does not overwrite the [=session history entry/app history state=] of the [=session history/current entry=] for cross-document navigations.
1. Otherwise, if |navigationType| is not "{{AppHistoryNavigationType/traverse}}", then [=finalize with an aborted navigation error=] given |appHistory| and |ongoingNavigation|.
1. Otherwise, if |navigationType| is not "{{AppHistoryNavigationType/traverse}}" and |event|'s {{AppHistoryNavigateEvent/signal}}'s [=AbortSignal/aborted flag=] is set, then [=finalize with an aborted navigation error=] given |appHistory| and |ongoingNavigation|.
<p class="note">If |navigationType| is "{{AppHistoryNavigationType/traverse}}", then we will [=finalize with an aborted navigation error=] in [=perform an app history traversal=].
1. Return |shouldContinue|.
</div>

<div algorithm>
To <dfn>finalize with an aborted navigation error</dfn> given an {{AppHistory}} |appHistory|, an [=app history API navigation=] or null |ongoingNavigation|, and an optional {{DOMException}} |error|:

1. Let |signal| be null.
1. If |appHistory|'s [=AppHistory/ongoing navigate event=] is non-null, then:
1. Set |signal| to the value of |appHistory|'s [=AppHistory/ongoing navigate event=]'s {{AppHistoryNavigateEvent/signal}} property.
1. Set |appHistory|'s [=AppHistory/ongoing navigate event=]'s [=Event/canceled flag=] to true.
1. Set |appHistory|'s [=AppHistory/ongoing navigate event=] to null.
1. Otherwise, set |signal| to |appHistory|'s [=AppHistory/post-navigate event ongoing navigation signal=].
1. Set |appHistory|'s [=AppHistory/post-navigate event ongoing navigation signal=] to null.
1. If |signal| is not null, then [=AbortSignal/signal abort=] on |signal|.
1. If |appHistory|'s [=AppHistory/ongoing navigation signal=] is non-null, then:
1. [=AbortSignal/signal abort=] on |appHistory|'s [=AppHistory/ongoing navigation signal=].
1. Set |appHistory|'s [=AppHistory/ongoing navigation signal=] to null.
1. If |error| was not given, then set |error| to a [=new=] "{{AbortError}}" {{DOMException}}, created in |appHistory|'s [=relevant Realm=].
1. If |appHistory|'s [=AppHistory/transition=] is not null, then:
1. [=Reject=] |appHistory|'s [=AppHistory/transition=]'s [=AppHistoryTransition/finished promise=] with |error|.
Expand All @@ -1192,13 +1189,14 @@ The <dfn attribute for="AppHistoryDestination">sameDocument</dfn> getter steps a
1. [=Reject=] |ongoingNavigation|'s [=app history API navigation/returned promise=] with |error|.
1. Perform |ongoingNavigation|'s [=app history API navigation/cleanup step=].
1. [=Fire an event=] named {{AppHistory/navigateerror}} at |appHistory| using {{ErrorEvent}}, with {{ErrorEvent/error}} initialized to |error|, and {{ErrorEvent/message}}, {{ErrorEvent/filename}}, {{ErrorEvent/lineno}}, and {{ErrorEvent/colno}} initialized to appropriate values that can be extracted from |error| and the current JavaScript stack in the same underspecified way the user agent typically does for the <a spec="HTML">report an exception</a> algorithm.
<p class="note">Thus, for example, if this algorithm is reached because of a call to {{Window/stop()|window.stop()}}, these properties would probably end up initialized based on the line of script that called {{Window/stop()|window.stop()}}. But if it's because the user clicked the stop button, these properties would probably end up with default values like the empty string or 0.
<p class="note">Thus, for example, if this algorithm is reached because of a call to {{Window/stop()|window.stop()}}, these properties would probably end up initialized based on the line of script that called {{Window/stop()|window.stop()}}. But if it's because the user clicked the stop button, these properties would probably end up with default values like the empty string or 0.
</div>

<div algorithm>
To <dfn>inform app history about canceling navigation</dfn> in a [=browsing context=] |bc|:

1. Let |appHistory| be |bc|'s [=browsing context/active window=]'s [=Window/app history=].
1. If |appHistory|'s [=AppHistory/ongoing navigation signal=] is null, then return.
1. Let |ongoingNavigation| be |appHistory|'s [=AppHistory/ongoing non-traverse navigation=].
1. If |ongoingNavigation| is null, and the navigation being canceled is an "<a for="history handling behavior">`entry update`</a>" navigation that originally came from traversal to a [=session history entry=] |she|, then:
<p class="advisement">This predicate should be made more precise when we define navigation cancelation in detail.</p>
Expand Down

0 comments on commit 90e9f72

Please sign in to comment.