Skip to content

Commit 39072b4

Browse files
committed
Add a browsingContext.traverseHistory command
This traverses the history by a specified `delta` (e.g. +1 for forward, or -1 for back). Like other navigation commands the `wait` parameter controls whether to return as soon as the history traversal starts, or wait for a specified level of completeness. Mush like other navigation commands, history traversal is tracked with a unique navigation id. Typically history traversal results in a navigation, but in the case of the history entry being in the bfcache, no navigation is necessary. In this case any non-"none" value for wait will return once the `pageshow` event is fired, and the `persisted` attribute of the return value is set to `true`. This model differs somewhat from the CDP model where one navigates to an explicit history entry and failure is only possible if the entry id is invalid. But back/forwward only seems closer to the use cases we have, and allowing events to be traced to a specific traversal seems consistent with the way we handle other navigation-related events.
1 parent bc60336 commit 39072b4

File tree

1 file changed

+159
-6
lines changed

1 file changed

+159
-6
lines changed

index.bs

Lines changed: 159 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ spec: HTML; urlPrefix: https://html.spec.whatwg.org/
107107
text: session history; url: session-history
108108
text: set up a window environment settings object; url: set-up-a-window-environment-settings-object
109109
text: set up a worker environment settings object; url: set-up-a-worker-environment-settings-object
110+
text: traverse the history by a delta; url: traverse-the-history-by-a-delta
110111
text: worker event loop; url: worker-event-loop-2
111112
text: worklet global scopes; url: concept-document-worklet-global-scopes
112113
</pre>
@@ -1700,7 +1701,8 @@ navigation status</dfn> struct, which has the following items:
17001701
BrowsingContextCommand = (
17011702
BrowsingContextGetTreeCommand //
17021703
BrowsingContextNavigateCommand //
1703-
BrowsingContextReloadCommand
1704+
BrowsingContextReloadCommand //
1705+
BrowsingContextTraverseHistoryCommand
17041706
)
17051707
</pre>
17061708

@@ -1710,7 +1712,8 @@ BrowsingContextCommand = (
17101712

17111713
BrowsingContextResult = (
17121714
BrowsingContextGetTreeResult //
1713-
BrowsingContextNavigateResult
1715+
BrowsingContextNavigateResult //
1716+
BrowsingContextTraverseHistoryResult
17141717
)
17151718

17161719
BrowsingContextEvent = (
@@ -2112,20 +2115,161 @@ The [=remote end steps=] with |command parameters| are:
21122115
1. Let |ignore cache| be the the value of the <code>ignoreCache</code> field of |command
21132116
parameters| if present, or false otherwise.
21142117

2115-
1. Let |wait condition| be the value of the <code>wait</code> field of |command
2116-
parameters| if present, or "<code>none</code>" otherwise.
2117-
21182118
1. Let |document| be |context|'s [=active document=].
21192119

21202120
1. Let |URL| be |document|'s <a spec=DOM>URL</a>.
21212121

2122-
1. Let |request| be a new [=/request=] whose URL is |URl|.
2122+
1. Let |request| be a new [=/request=] whose URL is |URL|.
21232123

21242124
1. Return the result of [=await a navigation=] with |context|, |request|,
21252125
history handling "<code>reload</code>", and ignore cache |ignore cache|.
21262126

21272127
</div>
21282128

2129+
#### The browsingContext.traverseHistory Command #### {#command-browsingContext-traverseHistory}
2130+
2131+
The <dfn export for=commands>browsingContext.traverseHistory</dfn> command
2132+
traverses the history of a given context by a delta.
2133+
2134+
<dl>
2135+
<dt>Command Type</dt>
2136+
<dd>
2137+
<pre class="cddl remote-cddl">
2138+
BrowsingContextTraverseHistoryCommand = {
2139+
method: "browsingContext.traverseHistory",
2140+
params: BrowsingContextTraverseHistoryParameters
2141+
}
2142+
2143+
BrowsingContextTraverseHistoryParameters = {
2144+
context: BrowsingContext,
2145+
delta: int,
2146+
?wait: ReadinessState,
2147+
}
2148+
</pre>
2149+
</dd>
2150+
<dt>Return Type</dt>
2151+
<dd>
2152+
<pre class="cddl local-cddl">
2153+
BrowsingContextTraverseHistoryResult = {
2154+
navigation: Navigation / null,
2155+
?persisted: bool
2156+
url: text,
2157+
}
2158+
</pre>
2159+
</dd>
2160+
</dl>
2161+
2162+
<div algorithm="remote end steps for browsingContext.traverseHistory">
2163+
The [=remote end steps=] with |command parameters| are:
2164+
2165+
1. Let |context id| be the value of the <code>context</code> field of
2166+
|command parameters|.
2167+
2168+
1. Let |context| be the result of [=trying=] to [=get a browsing context=]
2169+
with |context id|.
2170+
2171+
1. Assert: |context| is not null.
2172+
2173+
1. Let |delta| be the value of the <code>delta</code> field of |command
2174+
parameters|.
2175+
2176+
1. Let |wait condition| be the value of the <code>wait</code> field of |command
2177+
parameters| if present, or "<code>none</code>" otherwise.
2178+
2179+
1. Let |navigation id| be the string representation of a
2180+
[[!RFC4122|UUID]] based on truly random, or pseudo-random numbers.
2181+
2182+
1. [=Traverse the history by a delta=] given |delta|, |context|, and
2183+
|navigation id|.
2184+
2185+
1. Let (|event received|, |navigate status|) be [=await=] given
2186+
«"<code>navigation started</code>", "<code>navigation failed</code>",
2187+
"<code>fragment navigated</code>", "<code>pop state</code>"», and
2188+
|navigation id|.
2189+
2190+
1. Assert: |navigate status|'s id is |navigation id|.
2191+
2192+
1. If |navigate status|'s status is "<code>complete</code>":
2193+
2194+
1. Let |body| be a [=map=] matching the
2195+
<code>BrowsingContextTraverseHistoryResult</code> production, with the
2196+
<code>navigation</code> field set to |navigation id|, and the
2197+
<code>url</code> field set to the result of the [=URL serializer=] given
2198+
|navigate status|'s url.
2199+
2200+
1. Return [=success=] with data |body|.
2201+
2202+
1. If |navigate status|'s status is "<code>canceled</code>" return [=error=]
2203+
with [=error code=] [=unknown error=].
2204+
2205+
1. Assert: |navigate status|'s status is "<code>pending</code>" and
2206+
|navigation id| is not null.
2207+
2208+
1. If |wait condition| is "<code>none</code>":
2209+
2210+
1. Let |body| be a [=map=] matching the
2211+
<code>BrowsingContextTraverseHistoryResult</code> production, with the
2212+
<code>navigation</code> field set to |navigation id|, and the
2213+
<code>url</code> field set to the result of the [=URL serializer=] given
2214+
|navigate status|'s url.
2215+
2216+
1. If |wait condition| is "<code>interactive</code>", let |event name| be
2217+
"<code>domContentLoaded</code>", otherwise let |event name| be
2218+
"<code>load</code>".
2219+
2220+
1. Let (|event received|, |status|) be [=await=] given «|event name|,
2221+
"<code>download started</code>", "<code>navigation aborted</code>",
2222+
"<code>navigation failed</code>", "<code>page show</code>"», and |navigation
2223+
id|.
2224+
2225+
1. If |event received| is "<code>navigation failed</code>"
2226+
return [=error=] with [=error code=] [=unknown error=].
2227+
2228+
1. If event received is "<code>page show</code>", let |persisted| be true,
2229+
otherwise let |persisted| be false.
2230+
2231+
1. Let |body| be a [=map=] matching the
2232+
<code>BrowsingContextTraverseHistoryResult</code> production, with the
2233+
<code>navigation</code> field set to |status|'s id, the
2234+
<code>persisted</code> field set to |persisted|, and the <code>url</code>
2235+
field set to the result of the [=URL serializer=] given |status|'s url.
2236+
2237+
1. Return [=success=] with data |body|.
2238+
2239+
</div>
2240+
2241+
<div algorithm>
2242+
2243+
The <dfn export>WebDriver-BiDi page show</dfn> steps given <var
2244+
ignore>context</var> and |navigation status| are:
2245+
2246+
Issue: Do we want to expose a `browsingContext.pageShow event? In that case we'd
2247+
need to call this whenever `pageshow` is going to be emitted, not just on
2248+
bfcache restore, and also add the persisted status to the data.
2249+
2250+
1. If the [=current session=] is null, return.
2251+
2252+
1. Let |navigation id| be |navigation status|'s id.
2253+
2254+
1. [=Resume=] with "<code>page show</code>", |navigation id|, and
2255+
|navigation status|.
2256+
2257+
</div>
2258+
2259+
<div algorithm>
2260+
2261+
The <dfn export>WebDriver-BiDi pop state</dfn> steps given <var
2262+
ignore>context</var> and |navigation status| are:
2263+
2264+
1. If the [=current session=] is null, return.
2265+
2266+
1. Let |navigation id| be |navigation status|'s id.
2267+
2268+
1. [=Resume=] with "<code>pop state</code>", |navigation id|, and
2269+
|navigation status|.
2270+
2271+
</div>
2272+
21292273

21302274
### Events ### {#module-contexts-events}
21312275

@@ -2493,6 +2637,15 @@ failed</dfn> steps given |context| and |navigation status|:
24932637

24942638
1. Let |navigation id| be |navigation status|'s id.
24952639

2640+
1. If |navigation id| is null, then return.
2641+
2642+
Issue: The idea here is that we only get events if the navigation was
2643+
initiated by us and got far enough to have an id. In particular we wouldn't
2644+
get events for e.g. a page doing <code>history.back()</code> on a page where
2645+
that would fail. But maybe we want the actual invariant to be that we only
2646+
get a <code>navigationFailed</code> event if we already got a
2647+
<code>navigationStarted</code> event.
2648+
24962649
1. Let |related browsing contexts| be a set containing |context|.
24972650

24982651
1. [=Resume=] with "<code>navigation failed</code>", |navigation id|, and |navigation status|.

0 commit comments

Comments
 (0)