Skip to content

Commit

Permalink
Editorial: expose "wait for timeout"
Browse files Browse the repository at this point in the history
This factors out a new algorithm which can be used by postTask() (https://wicg.github.io/scheduling-apis/#schedule-a-posttask-task) and AbortSignal.timeout() (whatwg/dom#1032), ensuring that they correctly contribute to idle deadline computation and in general share all the appropriate logic with setTimeout() and setInterval().

This also exports the "timer task source" term since AbortSignal.abort() will want to use that.
  • Loading branch information
domenic committed Nov 23, 2021
1 parent bb7bde0 commit 66af549
Showing 1 changed file with 77 additions and 41 deletions.
118 changes: 77 additions & 41 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -93936,7 +93936,7 @@ import "https://example.com/foo/../module2.mjs";</code></pre>
</ol>
</li>

<li>
<li id="idle-deadline-computation">
<p>If all of the following are true

<ul class="brief">
Expand Down Expand Up @@ -96426,12 +96426,21 @@ enum <dfn enum>DOMParserSupportedType</dfn> {

<div w-nodev>

<p>Objects that implement the <code>WindowOrWorkerGlobalScope</code> mixin have a <dfn
export>map of active timers</dfn>, which is a <span>map</span>, initially empty. Each
<span data-x="map key">key</span> in this map is identified by a number, which must be unique
within the list for the lifetime of the object that implements the
<code>WindowOrWorkerGlobalScope</code> mixin, and each <span data-x="map value">value</span> is a
<code>DOMHighResTimeStamp</code>, representing the expiry time for that timer.</p>
<p>Objects that implement the <code>WindowOrWorkerGlobalScope</code> mixin have a <dfn export>map
of active timers</dfn>, which is a <span>map</span>, initially empty. Each <span data-x="map
key">key</span> in this map is an identifier for a timer, and each <span data-x="map
value">value</span> is a <code>DOMHighResTimeStamp</code>, representing the expiry time for that
timer.</p>

<p class="note">For entries put in the <span>map of active timers</span> by the <span>timer
initialization steps</span>, i.e., by <code data-x="dom-setTimeout">setTimeout()</code> and <code
data-x="dom-setInterval">setInterval()</code>, the keys are numbers. For other specifications
that use the <span>wait for a timeout</span> algorithm, the identifier is a unique non-numeric
value. Only the numeric-keyed timers are affected by <code
data-x="dom-clearTimeout">clearTimeout()</code> and <code
data-x="dom-clearInterval">clearInterval()</code>, but all timers contribute to <a
href="#idle-deadline-computation">idle deadline computation</a>, and are cleared when the
relevant global is destroyed.</p>

<hr>

Expand Down Expand Up @@ -96580,10 +96589,57 @@ enum <dfn enum>DOMParserSupportedType</dfn> {

<li><p>Set <var>task</var>'s <dfn>timer nesting level</dfn> to <var>nesting level</var>.</p></li>

<li><p>Let <var>completionStep</var> be an algorithm step which <span data-x="queue a global
task">queues a global task</span> on the <dfn export>timer task source</dfn> given
<var>global</var> to run <var>task</var>.</p></li>

<li>
<p><span>Wait for a timeout</span> given <var>global</var>, "<code
data-x="">setTimeout/setInterval</code>", <var>timeout</var>, <var>completionStep</var>, and
<var>handle</var>.</p>

<p class="note">Once the task has been processed, if <var>repeat</var> is false, it is safe to
remove the entry for <var>handle</var> from the <span>map of active timers</span> (there is no
way for the entry's existence to be detected past this point, so it does not technically matter
one way or the other).</p>
</li>

<li><p>Return <var>id</var>.</p></li>
</ol>

<p class="note">Argument conversion as defined by Web IDL (for example, invoking <code
data-x="">toString()</code> methods on objects passed as the first argument) happens in the
algorithms defined in Web IDL, before this algorithm is invoked.</p>

<div class="example">
<p>So for example, the following rather silly code will result in the log containing "<code
data-x="">ONE&nbsp;TWO&nbsp;</code>":</p>

<pre><code class="js">var log = '';
function logger(s) { log += s + ' '; }

setTimeout({ toString: function () {
setTimeout("logger('ONE')", 100);
return "logger('TWO')";
} }, 100);</code></pre>
</div>

<p>To <dfn export>wait for a timeout</dfn>, given a <code>WindowOrWorkerGlobalScope</code>
<var>global</var>, a string <var>orderingIdentifier</var>, a number <var>milliseconds</var>, a
set of steps <var>completionSteps</var>, and an optional value <var>timerKey</var>:</p>

<ol>
<li><p>Assert: if <var>timerKey</var> is given, then the caller of this algorithm is the
<span>timer initialization steps</span>. (Other specifications must not pass
<var>timerKey</var>.)</p></li>

<li><p>If <var>timerKey</var> is not given, set it to a new unique non-numeric value.</p></li>

<li><p>Let <var>startTime</var> be the <span>current high resolution time</span>.</p></li>

<li><p><span data-x="map set">Set</span> <var>global</var>'s <span>map of active
timers</span>[<var>id</var>] to <var>startTime</var> plus <var>timeout</var>.</p></li>
timers</span>[<var>timerKey</var>] to <var>startTime</var> plus
<var>milliseconds</var>.</p></li>

<li>
<p>Run the following steps <span>in parallel</span>:</p>
Expand All @@ -96592,17 +96648,17 @@ enum <dfn enum>DOMParserSupportedType</dfn> {
<li>
<p>If <var>global</var> is a <code>Window</code> object, wait until <var>global</var>'s <span
data-x="concept-document-window">associated <code>Document</code></span> has been <span>fully
active</span> for a further <var>timeout</var> milliseconds (not necessarily
active</span> for a further <var>milliseconds</var> milliseconds (not necessarily
consecutively).</p>

<p>Otherwise, <var>global</var> is a <code>WorkerGlobalScope</code> object; wait
until <var>timeout</var> milliseconds have passed with the worker not suspended (not
<p>Otherwise, <var>global</var> is a <code>WorkerGlobalScope</code> object; wait until
<var>milliseconds</var> milliseconds have passed with the worker not suspended (not
necessarily consecutively).</p>
</li>

<li><p>Wait until any invocations of this algorithm that had the same <var>global</var>, that
started before this one, and whose <var>timeout</var> is equal to or less than this one's,
have completed.</p></li>
<li><p>Wait until any invocations of this algorithm that had the same <var>global</var> and
<var>orderingIdentifier</var>, that started before this one, and whose <var>milliseconds</var>
is equal to or less than this one's, have completed.</p></li>

<li>
<p>Optionally, wait a further <span>implementation-defined</span> length of time.</p>
Expand All @@ -96614,37 +96670,17 @@ enum <dfn enum>DOMParserSupportedType</dfn> {
associated higher power usage.</p>
</li>

<li>
<p><span>Queue a global task</span> on the <dfn>timer task source</dfn> given
<var>global</var> to run <var>task</var>.</p>

<p class="note">Once the task has been processed, if <var>repeat</var> is false, it is safe
to remove the entry for <var>id</var> from the <span>map of active timers</span> (there is no
way for the entry's existence to be detected past this point, so it does not technically
matter one way or the other).</p>
</li>
<li><p>Perform <var>completionSteps</var>.</p></li>
</ol>
</li>

<li><p>Return <var>id</var>.</p></li>
</ol>

<p class="note">Argument conversion as defined by Web IDL (for example, invoking <code
data-x="">toString()</code> methods on objects passed as the first argument) happens in the
algorithms defined in Web IDL, before this algorithm is invoked.</p>

<div class="example">
<p>So for example, the following rather silly code will result in the log containing "<code
data-x="">ONE&nbsp;TWO&nbsp;</code>":</p>

<pre><code class="js">var log = '';
function logger(s) { log += s + ' '; }

setTimeout({ toString: function () {
setTimeout("logger('ONE')", 100);
return "logger('TWO')";
} }, 100);</code></pre>
</div>
<p class="note"><span>Wait for a timeout</span> is meant to be used by other specifications that
want to wait on developer-supplied timeouts, in a similar manner to <code
data-x="dom-setTimeout">setTimeout()</code>. (Note, however, it does not have the nesting and
clamping behavior of <code data-x="dom-setTimeout">setTimeout()</code>.) Such specifications can
choose an <var>orderingIdentifier</var> to ensure ordering within their specification's timeouts,
while not constraining ordering with respect to other specification's timeouts.</p>

</div>

Expand Down

0 comments on commit 66af549

Please sign in to comment.