Skip to content

Commit

Permalink
Explicit algorithm for idle callback "deadline"
Browse files Browse the repository at this point in the history
The algorithm replaces the algorithm that is currently defined in prose
here: https://w3c.github.io/requestidlecallback/#the-idledeadline-interface).

It works as such:
- Timers can calculate their estimated next callback timestamps,
  based on their start time and document-inactive time so far.
- The deadline for idle tasks for an event loop is the earliest between:
  - The time until the next timer callback in this event loop is estimated
    to fire.
  - The time until the next render, estimated at16ms after the start of
    the previous task that had a rended opportunity, if there are
    pending requestAnimationFrame callbacks.
  - 50ms

TODO: the deadline is currently checked between windows, it needs to be
re-checked between callbacks in the same window.

See w3c/requestidlecallback#71
  • Loading branch information
noamr committed Nov 13, 2021
1 parent 54bff73 commit f87739e
Showing 1 changed file with 73 additions and 7 deletions.
80 changes: 73 additions & 7 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -93525,6 +93525,8 @@ import "https://example.com/foo/../module2.mjs";</code></pre>
which is initially false. It is used to prevent reentrant invocation of the <span>perform a
microtask checkpoint</span> algorithm.</p>

<p>Each <span>window event loop</span> has a <span>DOMHighResTimeStamp</span>
<dfn>estimated time of next render</dfn>, initially set to zero.</p>

<h5>Queuing tasks</h5>

Expand Down Expand Up @@ -93781,7 +93783,8 @@ import "https://example.com/foo/../module2.mjs";</code></pre>
</li>

<li><p>If <var>docs</var> is not empty, then set <var>hasARenderingOpportunity</var> to
true.</p></li>
true and set this's <var>estimated time of next render</var> to <var>taskStartTime</var>
plus 16.</p></li>

<li>
<p><i>Unnecessary rendering</i>: Remove from <var>docs</var> all <code>Document</code> objects
Expand Down Expand Up @@ -93895,7 +93898,7 @@ import "https://example.com/foo/../module2.mjs";</code></pre>
</li>

<li>
<p>If all of the following are true
<p>If all of the following are true:</p>

<ul class="brief">
<li>this is a <span>window event loop</span></li>
Expand All @@ -93907,10 +93910,49 @@ import "https://example.com/foo/../module2.mjs";</code></pre>
<li><var>hasARenderingOpportunity</var> is false</li>
</ul>

<p>then for each <code>Window</code> object whose <span>relevant agent</span>'s
<span data-x="concept-agent-event-loop">event loop</span> is this event loop, run the
<span>start an idle period algorithm</span>, passing the <code>Window</code>. <ref
spec="REQUESTIDLECALLBACK"></p>
<p>then:</p>

<ol>
<li><p>Let <var>maxDeadline</var> be <var>now</var> plus 50.</p></li>

<li><p>Let <var>windows</var> be all <code>Window</code> objects whose
<span>relevant agent</span>'s <span data-x="concept-agent-event-loop">event loop</span> is
this event loop.</p></li>

<li>
<p>For each <code>Window</code> <var>win</var> in <var>windows</var>:</p>

<ol>
<li><p>Let <var>deadline</var> be <var>maxDeadline</var>.

<li>
<p>For each <code>Window</code> <var>windowToCheck</var> in <var>windows</var>:</p>

<ol>
<li><p>If the result of calling <var>windowToCheck</var>'s
<span>estimate next callback time</span> is between <var>now</var> and
<var>deadline</var>, set <var>deadline</var> to that value.</p></li>

<li><p>If <var>windowToCheck</var>'s <span>map of animation frame callbacks</span> is not
empty and <var>windowToCheck</var>'s <span>estimated time of next render</span> is
between <var>now</var> and <var>deadline</var>, set <var>deadline</var> to that
value.</p></li>
</ol>

<p class="note">We need to run this step for every window to make sure any timeouts added
during the idle period algorithm are taken into account. A non-critical task
(requestIdleCallback) might schedule a critical task
(setTimeout / requetAnimationFrame).</p>
</li>

<li><p>If the <span>current high resolution time</span> is greater than <var>deadline</var>,
abort this loop.</p></li>

<li><p><span>Start an idle period algorithm</span> for <var>win</var> with
<var>deadline</var>. <ref spec=REQUESTIDLECALLBACK></p></li>
</ol>
</li>
</ol>
</li>

<li>
Expand Down Expand Up @@ -96328,7 +96370,8 @@ enum <dfn enum>DOMParserSupportedType</dfn> {
<p>Objects that implement the <code>WindowOrWorkerGlobalScope</code> mixin have a <dfn
export>list of active timers</dfn>. Each entry in this lists 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.</p>
<code>WindowOrWorkerGlobalScope</code> mixin, and has an <dfn>estimate next callback time</dfn>,
an algorithm returing a <span>DOMHighResTimestamp</span>.</p>

<hr>

Expand Down Expand Up @@ -96494,6 +96537,29 @@ enum <dfn enum>DOMParserSupportedType</dfn> {
<li><p>Let <var>task</var>'s <dfn>timer nesting level</dfn> be <var>nesting
level</var>.</p></li>

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

<li>
<p>Set the <span>estimate next callback time</span> algorithm for the entry in the
<span>list of active timers</span> associated with <var>handle</var> to the following steps:</p>

<ol>
<li>
<p>Let <var>estimatedCallbackTime</var> be <var>startTime</var> plus <var>timeout</var>,
plus the duration in milliseconds in which the document has not been
<span>fully active</span> since <var>startTime</var>, plus a number representing an
<span>implementation-defined</span> length of time in milliseconds.</p>
</li>

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

<li><p>If <var>estimatedCallbackTime</var> is less than <var>now</var>, return
<var>now</var>.</p></li>

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

<li><p>Return <var>handle</var>, and then continue running this algorithm
<span>in parallel</span>.</p></li>

Expand Down

0 comments on commit f87739e

Please sign in to comment.