Skip to content

Commit

Permalink
OK, this seems pretty good
Browse files Browse the repository at this point in the history
  • Loading branch information
domenic committed Mar 24, 2022
1 parent 3935bb1 commit 3fea46f
Showing 1 changed file with 56 additions and 10 deletions.
66 changes: 56 additions & 10 deletions spec.bs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ spec: html; urlPrefix: https://html.spec.whatwg.org/multipage/
text: document; url: history.html#she-document
text: policy container; url: history.html#she-policy-container
text: URL; url: history.html#she-url
text: scroll position data; url: history.html#she-scroll-position
text: scroll restoration mode; url: history.html#she-scroll-restoration-mode
for: history handling behavior
text: default; url: browsing-the-web.html#hh-default
text: reload; url: browsing-the-web.html#hh-reload
Expand Down Expand Up @@ -66,6 +68,7 @@ spec: html; urlPrefix: https://whatpr.org/html/6315/
text: containing navigable; for: browsing context; url: browsers.html#bc-navigable
text: active document; for: navigable; url: history.html#nav-document
text: navigable; url: history.html#navigable
text: navigable; for: Window; url: browsers.html#window-navigable
spec: uuid; type: dfn; urlPrefix: https://wicg.github.io/uuid/
text: generate a random UUID; url: #dfn-generate-a-random-uuid
</pre>
Expand Down Expand Up @@ -1042,6 +1045,7 @@ interface NavigateEvent : Event {

undefined transitionWhile(Promise<undefined> newNavigationAction,
optional NavigationTransitionWhileOptions options = {});
undefined restoreScroll();
};

dictionary NavigateEventInit : EventInit {
Expand Down Expand Up @@ -1149,6 +1153,8 @@ A {{NavigateEvent}} has a <dfn for="NavigateEvent">focus reset behavior</dfn>, a

A {{NavigateEvent}} has a <dfn for="NavigateEvent">scroll restoration behavior</dfn>, a {{NavigationScrollRestoration}}-or-null, initially null.

A {{NavigateEvent}} has a <dfn for="NavigateEvent">did process scroll restoration</dfn>, a boolean, initially false.

A {{NavigateEvent}} has a <dfn for="NavigateEvent">navigation action promises list</dfn>, which is a [=list=] of {{Promise}} objects, initially empty.

<div algorithm>
Expand All @@ -1168,6 +1174,15 @@ A {{NavigateEvent}} has a <dfn for="NavigateEvent">navigation action promises li
1. Set [=this=]'s [=NavigateEvent/scroll restoration behavior=] to |options|["{{NavigationTransitionWhileOptions/scrollRestoration}}"].
</div>

<div algorithm>
The <dfn method for="NavigateEvent">restoreScroll()</dfn> method steps are:

1. If [=this=]'s {{NavigateEvent/navigationType}} was not initialized to "{{NavigationNavigationType/traverse}}", then throw an "{{InvalidStateError}}" {{DOMException}}.
1. If [=this=]'s [=NavigateEvent/scroll restoration behavior=] is not "{{NavigationScrollRestoration/manual}}", then throw an "{{InvalidStateError}}" {{DOMException}}.
1. If [=this=]'s [=NavigateEvent/did process scroll restoration=] is true, then throw an "{{InvalidStateError}}" {{DOMException}}.
1. [=Restore scroll position data=] given [=this=]'s [=relevant global object=]'s [=Window/navigable=]'s [=navigable/active session history entry=].
</div>

<h3 id="navigate-event-destination">The {{NavigationDestination}} class</h3>

<xmp class="idl">
Expand Down Expand Up @@ -1322,8 +1337,8 @@ The <dfn attribute for="NavigationDestination">sameDocument</dfn> getter steps a
1. Set |navigation|'s [=Navigation/ongoing navigate event=] to |event|.
1. [=Assert=]: |navigation|'s [=Navigation/ongoing navigation signal=] is null.
1. Set |navigation|'s [=Navigation/ongoing navigation signal=] to |event|'s {{NavigateEvent/signal}}.
1. Set |appHistory|'s [=Navigation/focus changed during ongoing navigation=] to false.
1. Set |appHistory|'s [=Navigation/suppress normal scroll restoration during ongoing navigation=] to false.
1. Set |navigation|'s [=Navigation/focus changed during ongoing navigation=] to false.
1. Set |navigation|'s [=Navigation/suppress normal scroll restoration during ongoing navigation=] to false.
1. Let |dispatchResult| be the result of [=dispatching=] |event| at |navigation|.
1. Set |navigation|'s [=Navigation/ongoing navigate event=] to null.
1. If |dispatchResult| is false:
Expand All @@ -1350,15 +1365,15 @@ The <dfn attribute for="NavigationDestination">sameDocument</dfn> getter steps a
1. If |navigation|'s [=Navigation/transition=] is not null, then [=resolve=] |navigation|'s [=Navigation/transition=]'s [=NavigationTransition/finished promise=] with undefined.
1. Set |navigation|'s [=Navigation/transition=] to null.
1. If |ongoingNavigation| is non-null, then [=navigation API method navigation/resolve the finished promise=] for |ongoingNavigation|.
1. [=Potentially reset the focus=] given |appHistory| and |event|.
1. [=Potentially perform scroll restoration=] given TODO.
1. [=Potentially reset the focus=] given |navigation| and |event|.
1. [=Potentially perform scroll restoration=] given |navigation| and |event|.
and the following failure steps given reason |rejectionReason|:
1. If |event|'s {{NavigateEvent/signal}} is [=AbortSignal/aborted=], then abort these steps.
1. [=Fire an event=] named {{Navigation/navigateerror}} at |navigation| using {{ErrorEvent}}, with {{ErrorEvent/error}} initialized to |rejectionReason|, and {{ErrorEvent/message}}, {{ErrorEvent/filename}}, {{ErrorEvent/lineno}}, and {{ErrorEvent/colno}} initialized to appropriate values that can be extracted from |rejectionReason| in the same underspecified way the user agent typically does for the <a spec="HTML">report an exception</a> algorithm.
1. If |navigation|'s [=Navigation/transition=] is not null, then [=reject=] |navigation|'s [=Navigation/transition=]'s [=NavigationTransition/finished promise=] with |rejectionReason|.
1. Set |navigation|'s [=Navigation/transition=] to null.
1. If |ongoingNavigation| is non-null, then [=navigation API method navigation/reject the finished promise=] for |ongoingNavigation| with |rejectionReason|.
1. [=Potentially reset the focus=] given |appHistory| and |event|.
1. [=Potentially reset the focus=] given |navigation| and |event|.
<p class="note">Although we still [=potentially reset the focus=] for such failed transitions, we do <em>not</em> [=potentially perform scroll restoration=] for them.
1. Otherwise, if |ongoingNavigation| is non-null, then:
1. Set |ongoingNavigation|'s [=navigation API method navigation/serialized state=] to null.
Expand Down Expand Up @@ -1419,9 +1434,10 @@ The <dfn attribute for="NavigationDestination">sameDocument</dfn> getter steps a

1. Let |focusChanged| be |navigation|'s [=Navigation/focus changed during ongoing navigation=].
1. Set |navigation|'s [=Navigation/focus changed during ongoing navigation=] to false.
1. If |event|'s [=NavigateEvent/focus reset behavior=] is "{{NavigationFocusReset/manual}}", then return.
<p class="note">If it was left as null, then we treat that was "{{NavigationFocusReset/after-transition}}", and continue onward.
1. If |focusChanged| is true, then return.
1. If |event|'s [=NavigateEvent/navigation action promises list=]'s [=list/size=] is 0, then return.
1. If |event|'s [=NavigateEvent/focus reset behavior=] is "{{NavigationFocusReset/manual}}", then return.
<p class="note">If it was left as null, then we treat that as "{{NavigationFocusReset/after-transition}}", and continue onward.
1. Let |document| be |navigation|'s [=relevant global object=]'s [=associated Document=].
1. Let |focusTarget| be the <a spec="HTML">autofocus delegate</a> for |document|.
1. If |focusTarget| is null, then set |focusTarget| to |document|'s <a spec="HTML" lt="the body element">body element</a>.
Expand All @@ -1430,7 +1446,15 @@ The <dfn attribute for="NavigationDestination">sameDocument</dfn> getter steps a
</div>

<div algorithm>
To <dfn>potentially perform scroll restoration</dfn> given TODO...
To <dfn>potentially perform scroll restoration</dfn> given a {{Navigation}} object |navigation| and an {{NavigateEvent}} |event|:

1. If |event|'s [=NavigateEvent/navigation action promises list=]'s [=list/size=] is 0, then return.
1. If |event|'s {{NavigateEvent/navigationType}} was not initialized to "{{NavigationNavigationType/traverse}}", then return.
1. If |event|'s [=NavigateEvent/scroll restoration behavior=] is "{{NavigationScrollRestoration/manual}}", then return.
<p class="note">If it was left as null, then we treat that as "{{NavigationScrollRestoration/after-transition}}", and continue onward.
1. If |event|'s [=NavigateEvent/did process scroll restoration=] is true, then return.
1. Set |event|'s [=NavigateEvent/did process scroll restoration=] to true.
1. [=Restore scroll position data=] given |navigation|'s [=Navigation/current entry=]'s [=NavigationHistoryEntry/session history entry=].
</div>

<h2 id="NavigationHistoryEntry-class">Navigation API history entries</h2>
Expand Down Expand Up @@ -1828,9 +1852,31 @@ Update the <a spec="HTML">focus fixup rule</a> to additionally set the {{Documen

<h3 id="scroll-restoration-patches">Scroll restoration</h3>

To support the {{NavigationTransitionWhileOptions/scrollRestoration}} option, the following patches need to be made:
To support the {{NavigationTransitionWhileOptions/scrollRestoration}} option, as well as to fix <a href="https://github.com/whatwg/html/issues/7517">whatwg/html#7517</a>, the following patches need to be made:

Add a boolean, <dfn for="Document">has been scrolled by the user</dfn>, initially false, to {{Document}} objects. State that if the user scrolls the document, the user agent must set that document's [=Document/has been scrolled by the user=] to true. Modify the <a spec="HTML">unload a document</a> algorithm to set this back to false.

Modify the <a spec="HTML">restore persisted state</a> algorithm's first step to not perform scroll restoration if <var ignore>entry</var>'s [=session history entry/document=]'s [=relevant global object=]'s [=Window/navigation API=]'s [=Navigation/suppress normal scroll restoration during ongoing navigation=] is true.
<div algorithm>
Define the process of <dfn>restoring scroll position data</dfn> given a [=session history entry=] |entry| as follows:

1. Let |document| be |entry|'s [=session history entry/document=].
1. If |document|'s [=Document/has been scrolled by the user=] is true, then the user agent should return.
1. The user agent should attempt to use |entry|'s [=session history entry/scroll position data=] to restore the scroll positions of |document|'s <a spec="HTML">restorable scrollable regions</a>. The user agent may continue to attempt to do so periodically, until |document|'s [=Document/has been scrolled by the user=] becomes true.

<p class="note">This is formulated as an <em>attempt</em>, which is potentially repeated until success or until the user scrolls, due to the fact that relevant content indicated by the [=session history entry/scroll position data=] might take some time to load from the network.

<p class="note">Scroll restoration might be affected by scroll anchoring. [[CSS-SCROLL-ANCHORING-1]]
</div>

<div algorithm="restore persisted state">
With this in place, modify the <a spec="HTML">restore persisted state</a> algorithm's first step to read as follows:

1. If |entry|'s [=session history entry/scroll restoration mode=] is "{{ScrollRestoration/auto}}", and |entry|'s [=session history entry/document=]'s [=relevant global object=]'s [=Window/navigation API=]'s [=Navigation/suppress normal scroll restoration during ongoing navigation=] is false, then [=restore scroll position data=] given |entry|.

In addition to the existing note, add the following one:

<p class="note">If the [=Navigation/suppress normal scroll restoration during ongoing navigation=] boolean is true, then [=restoring scroll position data=] might still happen at a later point, as part of [=potentially perform scroll restoration|potentially performing scroll restoration=] for the relevant {{Navigation}} object, or via a {{NavigateEvent/restoreScroll()|navigateEvent.restoreScroll()}} method call.
</div>

<h3 id="cancel-navigation">Canceling navigation and traversals</h3>

Expand Down

0 comments on commit 3fea46f

Please sign in to comment.