From 0d5f28a20dfc26fe0c07d18afd46ece7d524ba7c Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Fri, 14 May 2021 16:13:30 -0400 Subject: [PATCH] Some updates... navigate event still pretty borked --- spec.bs | 56 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/spec.bs b/spec.bs index 4759493..a9c0049 100644 --- a/spec.bs +++ b/spec.bs @@ -46,6 +46,16 @@ spec: html; urlPrefix: https://html.spec.whatwg.org/multipage/ text: exceptionsEnabled; url: browsing-the-web.html#exceptions-enabled type: method for: Document; text: open(unused1, unused2); url: multipage/dynamic-markup-insertion.html#dom-document-open +spec: html; urlPrefix: https://whatpr.org/html/6315/ + type: dfn + text: traversable navigable; for: navigable; url: history.html#nav-traversable + text: current session history entry; for: navigable; url: history.html#nav-current-history-entry + text: get the session history entries; for: navigable; url: history.html#getting-session-history-entries + text: session history traversal queue; for: traversable navigable; url: history.html#tn-session-history-traversal-queue + text: step; for: session history entry; url: history.html#she-step + text: apply the history step; url: history.html#apply-the-history-step + text: checkForUserCancelation; for: apply the history step; url: history.html#apply-the-history-step + text: initiatorToCheck; for: apply the history step; url: history.html#apply-the-history-step spec: uuid; type: dfn; urlPrefix: https://wicg.github.io/uuid/ text: generate a random UUID; url: #dfn-generate-a-random-uuid @@ -457,8 +467,6 @@ Each {{AppHistory}} object has an associated navigate meth 1. If [=this=]'s [=AppHistory/current index=] is −1, then return [=a promise rejected with=] an "{{InvalidStateError}}" {{DOMException}}. - 1. If [=this=]'s [=AppHistory/entry list=][[=this=]'s [=AppHistory/current index=]]'s [=AppHistoryEntry/session history entry=]'s [=session history entry/app history key=] equals |key|, then return [=a promise resolved with=] undefined. - 1. If [=this=]'s [=AppHistory/entry list=] does not contain any {{AppHistoryEntry}} whose [=AppHistoryEntry/session history entry=]'s [=session history entry/app history key=] equals |key|, then return [=a promise rejected with=] an "{{InvalidStateError}}" {{DOMException}}. 1. Return the result of [=performing an app history traversal=] given [=this=], |key|, and |options|. @@ -485,29 +493,53 @@ Each {{AppHistory}} object has an associated navigate meth
+

The following algorithm is specified in terms of the session history rewrite pull request against the HTML Standard, because the existing session history traversal infrastructure is broken enough that it's hard to build on. It is expected to track that work as it continues.

+ To perform an app history traversal given an {{AppHistory}} object |appHistory|, a string |key|, and an {{AppHistoryNavigationOptions}} |options|: 1. If |appHistory|'s [=relevant global object=]'s [=associated Document=] is not [=Document/fully active=], then return [=a promise rejected with=] an "{{InvalidStateError}}" {{DOMException}}. 1. If |appHistory|'s [=relevant global object=]'s [=associated Document=]'s unload counter is greater than 0, then return [=a promise rejected with=] an "{{InvalidStateError}}" {{DOMException}}. - 1. Let |jsh| be |appHistory|'s [=relevant global object=]'s [=Window/browsing context=]'s [=top-level browsing context=]'s joint session history. + 1. If |appHistory|'s [=AppHistory/entry list=][|appHistory|'s [=AppHistory/current index=]]'s [=AppHistoryEntry/session history entry=]'s [=session history entry/app history key=] equals |key|, then return [=a promise resolved with=] undefined. - 1. Let |currentEntryIndex| be the index of the current entry within |jsh|. + 1. Let |navigateInfo| be |options|["{{AppHistoryNavigationOptions/navigateInfo}}"] if it [=map/exists=], or undefined otherwise. - 1. Let |destinationIndex| be the index of the closest [=session history entry=] to the current entry, such that either that entry's [=session history entry/app history key=] equals |key|, or that entry is "standing in place of" another entry whose [=session history entry/app history key=] equals |key|. Here, |entryA| "standing in place of" entryB means that they occupy the same "slot" within the joint session history, but only |entryA| is included because it most recently became the [=session history/current entry=] of its [=session history=]. + 1. Let |navigable| be |appHistory|'s [=relevant global object=]'s [=associated Document=]'s navigable. -

This imprecise phrasing will go away when the great session history overhaul documented in whatwg/html#5767 is completed and we have a clear inventory of all [=session history entries=] in each slot in the joint session history. + 1. Let |traversable| be |navigable|'s [=navigable/traversable navigable=]. - 1. [=Assert=]: exactly one such entry must exist. + 1. Let |initiatorBC| be |appHistory|'s [=relevant global object=]'s [=Window/browsing context=]. - 1. If |appHistory|'s [=relevant global object=]'s [=Window/browsing context=] is not allowed to navigate any of the browsing contexts which would be navigated by traversing to |destinationIndex|, then return [=a promise rejected with=] a "{{SecurityError}}" {{DOMException}}. + 1. Let |promise| be [=a new promise=] created in |appHistory|'s [=relevant Realm=]. -

This is super-vague. And probably cannot be determined synchronously. Revisit this after whatwg/html#5767. + 1. [=parallel queue/Enqueue the following steps=] on |traversable|'s [=traversable navigable/session history traversal queue=]: - 1. Let |navigateInfo| be |options|["{{AppHistoryNavigationOptions/navigateInfo}}"] if it [=map/exists=], or undefined otherwise. + 1. Let |navigableEntries| be the result of [=navigable/getting the session history entries=] given |navigable|. + + 1. Let |targetEntry| be the [=session history entry=] in |navigableEntries| whose [=session history entry/app history key=] equals |key|. If no such entry exists, then: + + 1. [=Reject=] |promise| with an "{{InvalidStateError}}" {{DOMException}}. + + 1. Abort these steps. - 1. Traverse the history by a delta given |destinationIndex| − |currentEntryIndex| and |appHistory|'s [=relevant global object=]'s [=Window/browsing context=], with [=traverse the history by a delta/appHistoryInfo=] set to |navigateInfo|. +

This can occur if the |appHistory| object's view of session history is outdated, which can happen for brief periods while all the relevant threads and processes are being synchronized in reaction to a history change (such as the user clearing their history). + + 1. Assert: |targetEntry| is not |navigable|'s [=navigable/current session history entry=]. + + 1. Let |targetStep| be |targetEntry|'s [=session history entry/step=]. + + 1. [=Apply the history step=] |targetStep| to |traversable|, with [=apply the history step/checkForUserCancelation=] set to true, [=apply the history step/initiatorToCheck=] set to |initiatorBC|, and [=apply the history step/appHistoryInfo=] set to |navigateInfo|. + + - If this aborts due to user-canceled unloading, then [=reject=] |promise| with an "{{AbortError}}" {{DOMException}}. + + - If this aborts due to the initiator allowed-to-navigate check, then [=reject=] |promise| with a "{{SecurityError}}" {{DOMException}}. + + - TODO: deal with another traversal aborting this one. (The HTML spec PR doesn't support this yet.) Should result in "{{AbortError}}" {{DOMException}}. + +

Eventually [=apply the history step=] will have well-specified hooks for communicating these conditions back to its caller.

+ +TODO: this doesn't deal with the navigate event...

Event handlers

@@ -1060,6 +1092,8 @@ With the above infrastructure in place, we can actually fire and handle the {{Ap 1. If either |isSameDocument| is true or |userInvolvement| is not "[=user navigation involvement/browser UI=]", then: 1. Let |continue| be the result of [=firing a traversal navigate event=] at |appHistory| with [=fire a traversal navigate event/destinationEntry=] set to specified entry, [=fire a traversal navigate event/isSameDocument=] set to |isSameDocument|, [=fire a traversal navigate event/userInvolvement=] set to |userInvolvement|, and [=fire a traversal navigate event/info=] set to |appHistoryInfo|. 1. If |continue| is false, abort these steps. + +

The session history rewrite pull request will largely replace the above algorithm with [=apply the history step=].

Patches to session history