Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always fire CloseWatcher/dialog cancel events #10291

Merged
merged 1 commit into from
May 10, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
84 changes: 46 additions & 38 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -61403,10 +61403,12 @@ interface <dfn interface>HTMLDialogElement</dfn> : <span>HTMLElement</span> {
<span>this</span>'s <span>relevant global object</span>, with:</p>

<ul>
<li><p><i data-x="create-close-watcher-cancelAction">cancelAction</i> being to return the
result of <span data-x="concept-event-fire">firing an event</span> named <code
<li><p><i data-x="create-close-watcher-cancelAction">cancelAction</i> given
<var>canPreventClose</var> being to return the result of <span
data-x="concept-event-fire">firing an event</span> named <code
data-x="event-cancel">cancel</code> at <span>this</span>, with the <code
data-x="dom-Event-cancelable">cancelable</code> attribute initialized to true.</p></li>
data-x="dom-Event-cancelable">cancelable</code> attribute initialized to
<var>canPreventClose</var>.</p></li>

<li><p><i data-x="create-close-watcher-closeAction">closeAction</i> being to <span>close the
dialog</span> given <span>this</span> and null.</p></li>
Expand Down Expand Up @@ -82103,13 +82105,16 @@ body { display:none }
<ul>
<li><p>A <dfn data-x="close-watcher-window">window</dfn>, a <code>Window</code>.</p></li>

<li><p>A <dfn data-x="close-watcher-cancel-action">cancel action</dfn>, a list of steps. These
steps can never throw an exception, and return either true (to indicate that the caller will
proceed to the <span data-x="close-watcher-close-action">close action</span>) or false (to
indicate that the caller will bail out).</p></li>
<li><p>A <dfn data-x="close-watcher-cancel-action">cancel action</dfn>, an algorithm accepting a
boolean argument and returning a boolean. The argument indicates whether or not the cancel
action algorithm can prevent the close request from proceeding via the algorithm's return value.
If the boolean argument is true, then the algorithm can return either true to indicate that the
caller will proceed to the <span data-x="close-watcher-close-action">close action</span>, or
false to indicate that the caller will bail out. If the argument is false, then the return value
is always false. This algorithm can never throw an exception.</p></li>

<li><p>A <dfn data-x="close-watcher-close-action">close action</dfn>, a list of steps. These
steps can never throw an exception.</p></li>
<li><p>A <dfn data-x="close-watcher-close-action">close action</dfn>, an algorithm accepting no
arguments and returning nothing. This algorithm can never throw an exception.</p></li>

<li><p>An <dfn data-x="close-watcher-is-running-cancel">is running cancel action</dfn>
boolean.</p></li>
Expand Down Expand Up @@ -82194,38 +82199,37 @@ body { display:none }
<li><p>If <var>window</var>'s <span data-x="concept-document-window">associated
<code>Document</code></span> is not <span>fully active</span>, then return true.</p></li>

<li>
<p>If <var>window</var>'s <span>close watcher manager</span>'s <span data-x="close watcher
manager groups">groups</span>'s <span data-x="list size">size</span> is less than
<var>window</var>'s <span>close watcher manager</span>'s <span data-x="close watcher manager
allowed number of groups">allowed number of groups</span>, and <var>window</var> has
<span>history-action activation</span>, then:</p>
<li><p>Let <var>canPreventClose</var> be true if <var>window</var>'s <span>close watcher
manager</span>'s <span data-x="close watcher manager groups">groups</span>'s <span data-x="list
size">size</span> is less than <var>window</var>'s <span>close watcher manager</span>'s <span
data-x="close watcher manager allowed number of groups">allowed number of groups</span>, and
<var>window</var> has <span>history-action activation</span>; otherwise false.</p></li>

<ol>
<li><p>Set <var>closeWatcher</var>'s <span data-x="close-watcher-is-running-cancel">is running
cancel action</span> to true.</p></li>
<li><p>Set <var>closeWatcher</var>'s <span data-x="close-watcher-is-running-cancel">is running
cancel action</span> to true.</p></li>

<li><p>Let <var>shouldContinue</var> be the result of running <var>closeWatcher</var>'s <span
data-x="close-watcher-cancel-action">cancel action</span>.</p></li>
<li><p>Let <var>shouldContinue</var> be the result of running <var>closeWatcher</var>'s <span
data-x="close-watcher-cancel-action">cancel action</span> given
<var>canPreventClose</var>.</p></li>

<li><p>Set <var>closeWatcher</var>'s <span data-x="close-watcher-is-running-cancel">is running
cancel action</span> to false.</p></li>
<li><p>Set <var>closeWatcher</var>'s <span data-x="close-watcher-is-running-cancel">is running
cancel action</span> to false.</p></li>

<li>
<p>If <var>shouldContinue</var> is false, then:</p>
<li>
<p>If <var>shouldContinue</var> is false, then:</p>

<ol>
<li><p><span>Consume history-action user activation</span> given <var>window</var>.</p></li>
<ol>
<li><p><span>Assert</span>: <var>canPreventClose</var> is true.</p></li>

<li><p>Return false.</p></li>
</ol>
</li>
<li><p><span>Consume history-action user activation</span> given <var>window</var>.</p></li>

<li><p>Return false.</p></li>
</ol>

<p class="note">Note that since these substeps <span>consume history-action user
activation</span>, <span data-x="close-watcher-request-close">requesting to close</span> a
<span>close watcher</span> twice without any intervening <span>user activation</span> will skip
these substeps.</p>
<span>close watcher</span> twice without any intervening <span>user activation</span> will
result in <var>canPreventClose</var> being false the second time.</p>
</li>

<li><p><span data-x="close-watcher-close">Close</span> <var>closeWatcher</var>.</p></li>
Expand Down Expand Up @@ -82402,10 +82406,12 @@ dictionary <dfn dictionary>CloseWatcherOptions</dfn> {
object</span>, with:</p>

<ul>
<li><p><i data-x="create-close-watcher-cancelAction">cancelAction</i> being to return the
result of <span data-x="concept-event-fire">firing an event</span> named <code
<li><p><i data-x="create-close-watcher-cancelAction">cancelAction</i> given
<var>canPreventClose</var> being to return the result of <span
data-x="concept-event-fire">firing an event</span> named <code
data-x="event-cancel">cancel</code> at <span>this</span>, with the <code
data-x="dom-Event-cancelable">cancelable</code> attribute initialized to true.</p></li>
data-x="dom-Event-cancelable">cancelable</code> attribute initialized to
<var>canPreventClose</var>.</p></li>

<li><p><i data-x="create-close-watcher-closeAction">closeAction</i> being to <span
data-x="concept-event-fire">fire an event</span> named <code data-x="event-close">close</code>
Expand Down Expand Up @@ -82495,7 +82501,7 @@ picker.querySelector('.close-button').onclick = () => watcher.requestClose();</c
<code>CloseWatcher</code> from being destroying. A typical use case is as follows:</p>

<pre><code class="js">watcher.oncancel = async (e) => {
if (hasUnsavedData) {
if (hasUnsavedData && e.cancelable) {
e.preventDefault();

const userReallyWantsToClose = await askForConfirmation("Are you sure you want to close?");
Expand All @@ -82506,11 +82512,13 @@ picker.querySelector('.close-button').onclick = () => watcher.requestClose();</c
}
};</code></pre>

<p>For abuse prevention purposes, this event only fires if the page has <span>history-action
<p>For abuse prevention purposes, this event is only <code
data-x="dom-Event-cancelable">cancelable</code> if the page has <span>history-action
activation</span>, which will be lost after any given <span>close request</span>. This ensures
that if the user sends a close request twice in a row without any intervening user activation,
the request definitely succeeds; the second request ignores the <code
data-x="event-cancel">cancel</code> event handler and immediately closes the
the request definitely succeeds; the second request ignores any <code
data-x="event-cancel">cancel</code> event handler's attempt to call <code
data-x="dom-Event-preventDefault">preventDefault()</code> and proceeds to close the
<code>CloseWatcher</code>.</p>
</div>

Expand Down