You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This follows the explainer update in a430943. In the process, this closes#241 by rewriting the appropriate parts of the spec.
This mostly solves #32, but we will leave that open until we add the explainer and spec for consumable sticky activation, which will complete the feature.
text: current session history step; for: traversable navigable; url: history.html#tn-current-session-history-step
59
59
text: get all history steps; for: traversable navigable; url: history.html#getting-all-history-steps
60
60
text: step; for: session history entry; url: history.html#she-step
61
-
text: apply the history step; url: history.html#apply-the-history-step
61
+
text: apply the history step; url: browsing-the-web.html#apply-the-history-step
62
+
text: check if unloading is user-canceled; url: browsing-the-web.html#checking-if-unloading-is-user-canceled
63
+
text: getting the target history entry; url: browsing-the-web.html#getting-the-target-history-entry
64
+
text: get all navigables whose current session history entry will change or reload; url: browsing-the-web.html#get-all-navigables-whose-current-session-history-entry-will-change-or-reload
text: generate a random UUID; url: #dfn-generate-a-random-uuid
@@ -1231,6 +1236,8 @@ A {{NavigateEvent}} has a <dfn for="NavigateEvent">did process scroll behavior</
1231
1236
1232
1237
A {{NavigateEvent}} has a <dfn for="NavigateEvent">was intercepted</dfn>, a boolean, initially false.
1233
1238
1239
+
A {{NavigateEvent}} has a <dfn for="NavigateEvent">needs continue</dfn>, a boolean, initially false.
1240
+
1234
1241
A {{NavigateEvent}} has a <dfn for="NavigateEvent">navigation handler list</dfn>, which is a [=list=] of {{NavigationInterceptHandler}} callbacks, initially empty.
1235
1242
1236
1243
<div algorithm>
@@ -1362,8 +1369,7 @@ The <dfn attribute for="NavigationDestination">sameDocument</dfn> getter steps a
1362
1369
1. Set |destination|'s [=NavigationDestination/index=] to −1.
1363
1370
1. Set |destination|'s [=NavigationDestination/state=] to null.
1364
1371
1. Set |destination|'s [=NavigationDestination/is same document=] to true if |destinationEntry|'s [=session history entry/document=] is equal to |navigation|'s [=relevant global object=]'s [=associated Document=]; otherwise false.
1365
-
1. Let |result| be the result of performing the [=inner navigate event firing algorithm=] given |navigation|, "{{NavigationType/traverse}}", |event|, |destination|, |userInvolvement|, null, and null.
1366
-
1. [=Assert=]: |result| is true (traversals are never cancelable).
1372
+
1. Return the result of performing the [=inner navigate event firing algorithm=] given |navigation|, "{{NavigationType/traverse}}", |event|, |destination|, |userInvolvement|, null, and null.
1367
1373
</div>
1368
1374
1369
1375
<div algorithm="fire a non-traversal navigate event">
@@ -1406,9 +1412,16 @@ The <dfn attribute for="NavigationDestination">sameDocument</dfn> getter steps a
1406
1412
1407
1413
<p class="note">In this case the [=navigation API method navigation/committed promise=] and [=navigation API method navigation/finished promise=] will never fulfill, since we never create {{NavigationHistoryEntry}}s for the initial `about:blank` {{Document}} so we have nothing to [=resolve=] them with.
1408
1414
1. Return true.
1415
+
1. Let |browsingContext| be |navigation|'s [=relevant global object=]'s [=browsing context=].
1409
1416
1. Let |document| be |navigation|'s [=relevant global object=]'s [=associated document=].
1410
1417
1. If |document| <a spec="HTML">can have its URL rewritten</a> to |destination|'s [=NavigationDestination/URL=], and either |destination|'s [=NavigationDestination/is same document=] is true or |navigationType| is not "{{NavigationType/traverse}}", then initialize |event|'s {{NavigateEvent/canIntercept}} to true. Otherwise, initialize it to false.
1411
-
1. If |navigationType| is not "{{NavigationType/traverse}}", then initialize |event|'s {{Event/cancelable}} to true. Otherwise, initialize it to false.
1418
+
1. Let |traverseCanBeCanceled| be true if |userInvolvement| is not "<code>[=user navigation involvement/browser UI=]</code>" or |navigation|'s [=relevant global object=] has [=transient activation=]; otherwise, false.
1419
+
<p class="note">We are exploring the possibility of introducing the concept of a "consumable user activation" (i.e., a user activation that can be consumed like a transient user activation, but does not have the timeout of a transient user activation) instead of using transient activation here. This does not have a spec yet.
1420
+
1. If any of the following are true:
1421
+
* |navigationType| is not "{{NavigationType/traverse}}"; or
1422
+
* |browsingContext| is a [=top-level browsing context=] and |traverseCanBeCanceled| is true
1423
+
1424
+
then initialize |event|'s {{Event/cancelable}} to true. Otherwise, initialize it to false.
1412
1425
1. Initialize |event|'s {{Event/type}} to "{{Navigation/navigate}}".
1413
1426
1. Initialize |event|'s {{NavigateEvent/navigationType}} to |navigationType|.
1414
1427
1. Initialize |event|'s {{NavigateEvent/destination}} to |destination|.
@@ -1432,11 +1445,23 @@ The <dfn attribute for="NavigationDestination">sameDocument</dfn> getter steps a
1432
1445
1. Set |navigation|'s [=Navigation/focus changed during ongoing navigation=] to false.
1433
1446
1. Set |navigation|'s [=Navigation/suppress normal scroll restoration during ongoing navigation=] to false.
1434
1447
1. Let |dispatchResult| be the result of [=dispatching=] |event| at |navigation|.
1435
-
1. Set |navigation|'s [=Navigation/ongoing navigate event=] to null.
1436
1448
1. If |dispatchResult| is false:
1437
1449
1. If |navigationType| is not "{{NavigationType/traverse}}" and |event|'s {{NavigateEvent/signal}} is not [=AbortSignal/aborted=], then [=finalize with an aborted navigation error=] given |navigation| and |ongoingNavigation|.
1438
1450
<p class="note">If |navigationType| is "{{NavigationType/traverse}}", then we will [=finalize with an aborted navigation error=] in [=perform a navigation API traversal=].
1439
1451
1. Return false.
1452
+
1453
+
1. If |destination|'s [=NavigationDestination/is same document=] is true and |navigationType| is "{{NavigationType/traverse}}":
1454
+
1. Set |event|'s [=NavigateEvent/needs continue=] to true.
1455
+
1. Return true.
1456
+
1. Return the result of [=reacting to navigate event result=] given |navigation| and |event|.
1457
+
</div>
1458
+
1459
+
<div algorithm>
1460
+
To <dfn>react to `navigate` event result</dfn>, given a {{Navigation}} |navigation| and a {{NavigateEvent}} |event|:
1461
+
1. Let |document| be |navigation|'s [=relevant global object=]'s [=associated document=].
1462
+
1. Let |destination| be |event|'s {{NavigateEvent/destination}}.
1463
+
1. Let |ongoingNavigation| be |navigation|'s [=Navigation/ongoing navigation=].
1464
+
1. Let |navigationType| be |event|'s {{NavigateEvent/navigationType}}.
1440
1465
1. Let |endResultIsSameDocument| be true if |event|'s [=NavigateEvent/was intercepted=] is true or |destination|'s [=NavigationDestination/is same document=] is true.
1441
1466
1. [=Prepare to run script=] given |event|'s [=relevant settings object=].
@@ -1463,6 +1488,7 @@ The <dfn attribute for="NavigationDestination">sameDocument</dfn> getter steps a
1463
1488
<p class="note">There is a subtle timing difference between how [=waiting for all=] schedules its success and failure steps when given zero promises versus ≥1 promises. For most uses of [=waiting for all=], this does not matter. However, with this API, there are so many events and promise handlers which could fire around the same time that the difference is pretty easily observable: it can cause the event/promise handler sequence to vary. (Some of the events and promises involved include: {{Navigation/navigatesuccess}} / {{Navigation/navigateerror}}, {{Navigation/currententrychange}}, {{NavigationHistoryEntry/dispose}}, |ongoingNavigation|'s promises, and the {{NavigationTransition/finished|navigation.transition.finished}} promise.)
1464
1489
1. [=Wait for all=] of |promisesList|, with the following success steps:
1465
1490
1. If |event|'s {{NavigateEvent/signal}} is [=AbortSignal/aborted=], then abort these steps.
1491
+
1. If |event| equals |navigation|'s [=Navigation/ongoing navigate event=], set |navigation|'s [=Navigation/ongoing navigate event=] to null.
1466
1492
1. [=Fire an event=] named {{Navigation/navigatesuccess}} at |navigation|.
1467
1493
1. If |navigation|'s [=Navigation/transition=] is not null, then [=resolve=] |navigation|'s [=Navigation/transition=]'s [=NavigationTransition/finished promise=] with undefined.
1468
1494
1. Set |navigation|'s [=Navigation/transition=] to null.
@@ -1480,10 +1506,16 @@ The <dfn attribute for="NavigationDestination">sameDocument</dfn> getter steps a
1480
1506
1. Otherwise, if |ongoingNavigation| is non-null, then [=navigation API method navigation/clean up=] |ongoingNavigation|.
1481
1507
1. [=Clean up after running script=].
1482
1508
<p class="note">Per the <a href="#note-suppress-microtasks-during-navigation-events">previous note</a>, this stops suppressing any potential promise handler microtasks, causing them to run at this point or later.</p>
1483
-
1. If |event|'s [=NavigateEvent/was intercepted=] is true and |navigationType| is "{{NavigationType/push}}", "{{NavigationType/replace}}", or "{{NavigationType/reload}}", then return false.
1509
+
1. If |event|'s [=NavigateEvent/was intercepted=] is true, then return false.
1484
1510
1. Return true.
1485
1511
</div>
1486
1512
1513
+
<div algorithm>
1514
+
To <dfn>maybe continue the `navigate` event</dfn>, given a {{Navigation}} |navigation|:
1515
+
1. If |navigation|'s [=Navigation/ongoing navigate event=] is null, or |navigation|'s [=Navigation/ongoing navigate event=]'s [=NavigateEvent/needs continue=] is false, then return.
1516
+
1. [=React to navigate event result=] given |navigation| and |navigation|'s [=Navigation/ongoing navigate event=].
1517
+
</div>
1518
+
1487
1519
<div algorithm>
1488
1520
To <dfn>finalize with an aborted navigation error</dfn> given a {{Navigation}} |navigation|, a [=navigation API method navigation=] or null |ongoingNavigation|, and an optional {{DOMException}} |error|:
1489
1521
@@ -1843,12 +1875,57 @@ Expand the section of the navigation/traversal response handling which deals wit
<div algorithm="check if unloading is user-canceled">
1879
+
Modify the [=check if unloading is user-canceled=] algorithm as follows:
1880
+
1881
+
To [=check if unloading is user-canceled=] given a [=list=] of [=navigables=] |navigablesCrossingDocuments|, an optional [=navigable=] |traversable|, an optional integer |targetStep| (default null), and an optional [=user navigation involvement=] |userInvolvement| (default "<code>[=user navigation involvement/none=]</code>"):
1882
+
1. Let |unloadPromptShown| be false.
1883
+
1. Let |unloadPromptCanceled| be false.
1884
+
1. Let |changingNavigables| be a [=list=] of [=navigables=], initially empty.
1885
+
1. If |traversable| is not null and |targetStep| is not null, append the result of [=get all navigables whose current session history entry will change or reload=] given |traversable| and |targetStep| to |changingNavigables|.
1886
+
1. Otherwise, append |navigablesCrossingDocuments| to |changingNavigables|.
1887
+
1. Let |totalTasks| be the size of |changingNavigables|.
1888
+
1. Let |completedTasks| be 0.
1889
+
1. If |traversable| is not null and |changingNavigables| [=list/contains=] |traversable|:
1890
+
1. Let |targetEntry| be the result of [=getting the target history entry=] given |traversable| and |targetStep|.
1891
+
1. Let |isSameOrigin| be true if |targetEntry|'s [=session history entry/origin=] is the [=same origin|same=] as |traversable|'s [=navigable/current session history entry=]'s [=session history entry/origin=]; otherwise, false.
1892
+
1. [=Queue a global task=] on the [=navigation and traversal task source=] given |traversable|'s [=navigable/active window=] to run the following steps:
1893
+
1. If |isSameOrigin| is true:
1894
+
1. Let |navigateEventResult| be the result of [=firing a traversal navigate event=] at |traversable|'s [=navigable/active window=]'s [=Window/navigation API=] with <i>[=fire a traversal navigate event/destinationEntry=]</i> set to |targetEntry| and <i>[=fire a traversal navigate event/userInvolvement=]</i> set to |userInvolvement|.
1895
+
1. If |navigateEventResult| is false, then set |unloadPromptCanceled| to true.
1896
+
1. If |unloadPromptCanceled| is false and |navigablesCrossingDocuments| [=list/contains=] |traversable|:
1897
+
1. Run the steps to fire a beforeunload event (currently steps 6.1 thru 6.8 in the [=check if unloading is user-canceled=] steps).
1898
+
1. Increment |completedTasks|.
1899
+
1. Wait for |completedTasks| to be 1.
1900
+
1. If |unloadPromptCanceled| is true, then return "<code>refuse</code>";
1901
+
1. For each |navigable| of |changingNavigables|:
1902
+
1. If |navigable| equals |traversable|, then [=iteration/continue=].
1903
+
1. Let |targetEntry| be the result of [=getting the target history entry=] given |traversable| and |targetStep|.
1904
+
1. Let |isSameOrigin| be true if |targetEntry|'s [=session history entry/origin=] is the [=same origin|same=] as |navigable|'s [=navigable/current session history entry=]'s [=session history entry/origin=]; otherwise, false.
1905
+
1. [=Queue a global task=] on the [=navigation and traversal task source=] given |navigable|'s [=navigable/active window=] to run the following steps:
1906
+
1. If |isSameOrigin| is true:
1907
+
1. Let |navigateEventResult| be the result of [=firing a traversal navigate event=] at |navigable|'s [=navigable/active window=]'s [=Window/navigation API=] with <i>[=fire a traversal navigate event/destinationEntry=]</i> set to |targetEntry| and <i>[=fire a traversal navigate event/userInvolvement=]</i> set to |userInvolvement|.
1908
+
1. [=Assert=]: |navigateEventResult| is true.
1909
+
1. If |navigablesCrossingDocuments| [=list/contains=] |navigable|:
1910
+
1. Run the steps to fire a beforeunload event (currently steps 6.1 thru 6.8 in the [=check if unloading is user-canceled=] steps).
1911
+
1. Increment |completedTasks|.
1912
+
1. Wait for |completedTasks| to be |totalTasks|.
1913
+
1. If |unloadPromptCanceled| is true, then return "<code>refuse</code>".
1914
+
1. If |unloadPromptShown| is true, then return "<code>confirm</code>".
1915
+
1. Return "<code>no-prompt</code>".
1916
+
</div>
1917
+
1846
1918
<div algorithm="apply the history step">
1847
-
Modify the [=apply the history step=] algorithm as follows. Near the end of the algorithm, inside the queued task over each global (currently step 14.10), before potentially unloading or activating the history entry, add the following step:
1919
+
Modify the [=apply the history step=] algorithm as follows:
1848
1920
1849
-
1. [=Fire a traversal navigate event=] at <var ignore>displayedDocument</var>'s [=relevant global object=]'s [=Window/navigation API=] with <i>[=fire a traversal navigate event/destinationEntry=]</i> set to <var ignore>targetEntry</var> and <i>[=fire a traversal navigate event/userInvolvement=]</i> set to <var ignore>userInvolvement</var>.
1921
+
Change step 5 (which runs the [=check if unloading is user-canceled=] steps) to:
1922
+
1. If <var ignore>checkForUserCancelation</var> is true, and the result of [=checking if unloading is user-canceled=] given <var ignore>navigablesCrossingDocuments</var>, <var ignore>traversable</var>, <var ignore>targetStep</var> and <var ignore>userInvolvement</var> is "<code>refuse</code>", then return.
1850
1923
1851
1924
(Recall that we introduced the <var ignore>userInvolvement</var> parameter as part of [[#user-initiated-patches]].)
1925
+
1926
+
Before the update document for history step application (currently step 14.10.3), add the following step:
1927
+
1. If <var ignore>changingNavigableContinuation</var>'s [=update-only=] is true, [=maybe continue the navigate event=] given <var ignore>displayedDocument</var>'s [=relevant global object=]'s [=Window/navigation API=].
1928
+
1852
1929
</div>
1853
1930
1854
1931
<h3 id="navigate-event-download-patches">Download a hyperlink updates</h3>
0 commit comments