[html5] r8095 - [giow] (3) Refactor the timer code to match current practice in WebKit, Gecko, a [...]

whatwg at whatwg.org whatwg at whatwg.org
Fri Jul 26 16:27:46 PDT 2013


Author: ianh
Date: 2013-07-26 16:27:44 -0700 (Fri, 26 Jul 2013)
New Revision: 8095

Modified:
   complete.html
   index
   source
Log:
[giow] (3) Refactor the timer code to match current practice in WebKit, Gecko, and Blink (the ones whose source I could examine)
Fixing https://www.w3.org/Bugs/Public/show_bug.cgi?id=22631
Affected topics: HTML

Modified: complete.html
===================================================================
--- complete.html	2013-07-26 22:21:58 UTC (rev 8094)
+++ complete.html	2013-07-26 23:27:44 UTC (rev 8095)
@@ -73252,7 +73252,10 @@
 
    </dd>
 
-  </dl><p class=note>This API does not guarantee that timers will run exactly on schedule. Delays due
+  </dl><p class=note>Timers can be nested; after five such nested timers, however, the interval is
+  forced to be at least four milliseconds.</p>
+
+  <p class=note>This API does not guarantee that timers will run exactly on schedule. Delays due
   to CPU load, other tasks, etc, are to be expected.</p>
 
   <div class=impl>
@@ -73264,229 +73267,230 @@
   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><a href=#windowtimers>WindowTimers</a></code> interface.</p>
 
-  <hr><p>The <dfn id=dom-windowtimers-settimeout title=dom-windowtimers-setTimeout><code>setTimeout()</code></dfn> method must run
-  the following steps:
+  <hr><p>The <dfn id=dom-windowtimers-settimeout title=dom-windowtimers-setTimeout><code>setTimeout()</code></dfn> method must return
+  the value returned by the <a href=#timer-initialization-steps>timer initialization steps</a>, passing them the method's
+  arguments, the object on which the method for which the algorithm is running is implemented (a
+  <code><a href=#window>Window</a></code> or <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object) as the <var title="">method
+  context</var>, and the <var title="">repeat</var> flag set to false.</p>
 
-  <ol><li><p>Let <var title="">handle</var> be a user-agent-defined integer that is greater than zero
-   that will identify the timeout to be set by this call in the <a href=#list-of-active-timers>list of active
-   timers</a>.</li>
+  <p>The <dfn id=dom-windowtimers-setinterval title=dom-windowtimers-setInterval><code>setInterval()</code></dfn> method must
+  return the value returned by the <a href=#timer-initialization-steps>timer initialization steps</a>, passing them the
+  method's arguments, the object on which the method for which the algorithm is running is
+  implemented (a <code><a href=#window>Window</a></code> or <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object) as the <var title="">method context</var>, and the <var title="">repeat</var> flag set to true.</p>
 
-   <li><p>Add an entry to the <a href=#list-of-active-timers>list of active timers</a> for <var title="">handle</var>.</li>
+  <p>The <dfn id=dom-windowtimers-cleartimeout title=dom-windowtimers-clearTimeout><code>clearTimeout()</code></dfn> and <dfn id=dom-windowtimers-clearinterval title=dom-windowtimers-clearInterval><code>clearInterval()</code></dfn> methods must clear the
+  entry identified as <var title="">handle</var> from the <a href=#list-of-active-timers>list of active timers</a> of the
+  <code><a href=#windowtimers>WindowTimers</a></code> object on which the method was invoked, where <var title="">handle</var>
+  is the argument passed to the method, if any. (If <var title="">handle</var> does not identify an
+  entry in the <a href=#list-of-active-timers>list of active timers</a> of the <code><a href=#windowtimers>WindowTimers</a></code> object on which
+  the method was invoked, the method does nothing.)</p>
 
-   <li><p><a href=#get-the-timed-task>Get the timed task</a> <var title="">handle</var> in the <a href=#list-of-active-timers>list of active
-   timers</a>, and let <var title="">task</var> be the result. This algorithm uses the first
-   argument to the method (<var title="">handler</var>) and, if there are any, the third and
-   subsequent arguments to the method (<var title="">arguments</var>), to establish precisely what
-   <var title="">task</var> does.</li>
+  <hr><p>The <dfn id=timer-initialization-steps>timer initialization steps</dfn>, which are invoked with some method arguments, a <var title="">method context</var>, a <var title="">repeat</var> flag which can be true or false, and
+  optionally (and only if the <var title="">repeat</var> flag is true) a <var title="">previous
+  handle</var>, are as follows:</p>
 
-   <li><p>Let <var title="">timeout</var> be the second argument to the method, or zero if the
-   argument was omitted.</li>
+  <ol><li><p>Let <var title="">method context proxy</var> be <var title="">method context</var> if that
+   is a <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object, or else the <code><a href=#windowproxy>WindowProxy</a></code> that corresponds
+   to <var title="">method context</var>.</li>
 
-   <li><p>If the currently running <a href=#concept-task title=concept-task>task</a> is a task that was created
-   by the <code title=dom-windowtimers-setTimeout><a href=#dom-windowtimers-settimeout>setTimeout()</a></code> method, and <var title="">timeout</var> is less than 4, then increase <var title="">timeout</var> to 4.</li>
+   <li><p>If <var title="">previous handle</var> was provided, let <var title="">handle</var> be
+   <var title="">previous handle</var>; otherwise, let <var title="">handle</var> be a
+   user-agent-defined integer that is greater than zero that will identify the timeout to be set by
+   this call in the <a href=#list-of-active-timers>list of active timers</a>.</li>
 
-   <li><p>Return <var title="">handle</var>, and then continue running this algorithm
-   asynchronously.</li>
+   <li><p>If <var title="">previous handle</var> was not provided, add an entry to the <a href=#list-of-active-timers>list of
+   active timers</a> for <var title="">handle</var>.</li>
 
    <li>
 
-    <p>If the <a href=#method-context>method context</a> is a <code><a href=#window>Window</a></code> object, wait until the
-    <code><a href=#document>Document</a></code> associated with the <a href=#method-context>method context</a> has been <a href=#fully-active>fully
-    active</a> for a further <var title="">timeout</var> milliseconds (not necessarily
-    consecutively).</p>
+    <p>Let <var title="">task</var> be a <a href=#concept-task title=concept-task>task</a> that runs the
+    following substeps:</p>
 
-    <p>Otherwise, if the <a href=#method-context>method context</a> is a <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object,
-    wait until <var title="">timeout</var> milliseconds have passed with the worker not suspended
-    (not necessarily consecutively).</p>
+    <ol><li>
 
-    <p>Otherwise, act as described in the specification that defines that the
-    <code><a href=#windowtimers>WindowTimers</a></code> interface is implemented by some other object.</p>
+      <p>If the entry for <var title="">handle</var> in the <a href=#list-of-active-timers>list of active timers</a> has
+      been cleared, then abort this <a href=#concept-task title=concept-task>task</a>'s substeps.</p>
 
-   </li>
+     </li>
 
-   <li>
+     <li>
 
-    <p>Wait until any invocations of this algorithm that had the same <a href=#method-context>method context</a>,
-    that started before this one, and whose <var title="">timeout</var> is equal to or less than
-    this one's, have completed.</p>
+      <p>Run the appropriate set of steps from the following list:</p>
 
-    <p class=note>Argument conversion as defined by Web IDL (for example, invoking <code title="">toString()</code> methods on objects passed as the first argument) happens in the
-    algorithms defined in Web IDL, before this algorithm is invoked.</p>
+      <dl class=switch><dt>If the first method argument is a <code>Function</code></dt>
 
-    <div class=example>
+       <dd>
 
-     <p>So for example, the following rather silly code will result in the log containing "<code title="">ONE TWO </code>":</p>
+        <p>Call the <code>Function</code>. Use the third and subsequent method arguments (if any) as
+        the arguments for invoking the <code>Function</code>. Use <var title="">method context
+        proxy</var> as the <var title="">thisArg</var> for invoking the <code>Function</code>. <a href=#refsECMA262>[ECMA262]</a></p>
 
-     <pre>var log = '';
-function logger(s) { log += s + ' '; }
+       </dd>
 
-setTimeout({ toString: function () {
-  setTimeout("logger('ONE')", 100);
-  return "logger('TWO')";
-} }, 100);</pre>
+       <dt>Otherwise</dt>
 
-    </div>
+       <dd>
 
-   </li>
+        <ol><li><p>Let <var title="">script source</var> be the first method argument.</li>
 
-   <li>
+         <li><p>Let <var title="">script language</var> be JavaScript.</li>
 
-    <p>Optionally, wait a further user-agent defined length of time.</p>
+         <li>
 
-    <p class=note>This is intended to allow user agents to pad timeouts as needed to optimise the
-    power usage of the device. For example, some processors have a low-power mode where the
-    granularity of timers is reduced; on such platforms, user agents can slow timers down to fit
-    this schedule instead of requiring the processor to use the more accurate mode with its
-    associated higher power usage.</p>
+          <p>If <var title="">method context</var> is a <code><a href=#window>Window</a></code> object, let <var title="">global object</var> be <var title="">method context</var>, let <var title="">browsing context</var> be the <a href=#browsing-context>browsing context</a> with which <var title="">global object</var> is associated, let <var title="">document</var> and <var title="">referrer source</var> be the <code><a href=#document>Document</a></code> associated with <var title="">global object</var>, let <var title="">character encoding</var> be the <a href="#document's-character-encoding" title="document's character encoding">character encoding</a> of the <code><a href=#document>Document</a></code>
+          associated with <var title="">global object</var> (<a href=#sce-not-copy>this is a
+          reference, not a copy</a>), and let <var title="">base URL</var> be the <a href=#document-base-url title="document base URL">base URL</a> of the <code><a href=#document>Document</a></code> associated with <var title="">global object</var> (<a href=#sbu-not-copy>this is a reference, not a
+          copy</a>).</p>
 
-   </li>
+          <p>Otherwise, <var title="">method context</var> is a <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object;
+          let <var title="">global object</var>, <var title="">browsing context</var>, <var title="">document</var>, <var title="">referrer source</var>, <var title="">character
+          encoding</var>, and <var title="">base URL</var> be the <a href="#script's-global-object">script's global object</a>,
+          <a href="#script's-browsing-context">script's browsing context</a>, <a href="#script's-document">script's document</a>, <a href="#script's-referrer-source">script's
+          referrer source</a>, <a href="#script's-url-character-encoding">script's URL character encoding</a>, and <a href="#script's-base-url">script's
+          base URL</a> (respectively) of the <a href=#concept-script title=concept-script>script</a> that the
+          <a href=#run-a-worker>run a worker</a> algorithm created when it created <var title="">method
+          context</var>.</p>
 
-   <li>
+         </li>
 
-    <p><a href=#queue-a-task title="queue a task">Queue</a> the <a href=#concept-task title=concept-task>task</a> <var title="">task</var>.</p>
+         <li>
 
-    <p class=note>Once the task has been processed, it is safe to remove the entry for <var title="">handle</var> from the <a href=#list-of-active-timers>list of active timers</a> (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>
+          <p><a href=#create-a-script>Create a script</a> using <var title="">script source</var> as the script
+          source, the <a href=#url>URL</a> where <var title="">script source</var> can be found, <var title="">scripting language</var> as the scripting language, <var title="">global
+          object</var> as the global object, <var title="">browsing context</var> as the browsing
+          context, <var title="">document</var> as the document, <var title="">referrer source</var>
+          as the referrer source, <var title="">character encoding</var> as the URL character
+          encoding, and <var title="">base URL</var> as the base URL.</p>
 
-   </li>
+         </li>
 
-  </ol><hr><p>The <dfn id=dom-windowtimers-setinterval title=dom-windowtimers-setInterval><code>setInterval()</code></dfn> method must run
-  the following steps:
+        </ol></dd>
 
-  <ol><li><p>Let <var title="">handle</var> be a user-agent-defined integer that is greater than zero
-   that will identify the timeout to be set by this call in the <a href=#list-of-active-timers>list of active
-   timers</a>.</li>
+      </dl></li>
 
-   <li><p>Add an entry to the <a href=#list-of-active-timers>list of active timers</a> for <var title="">handle</var>.</li>
+     <li>
 
-   <li><p><a href=#get-the-timed-task>Get the timed task</a> <var title="">handle</var> in the <a href=#list-of-active-timers>list of active
-   timers</a>, and let <var title="">task</var> be the result. This algorithm uses the first
-   argument to the method (<var title="">handler</var>) and, if there are any, the third and
-   subsequent arguments to the method (<var title="">arguments</var>), to establish precisely what
-   <var title="">task</var> does.</li>
+      <p>If the <var title="">repeat</var> flag is true, then call <a href=#timer-initialization-steps>timer initialization
+      steps</a> again, passing them the same method arguments, the same <var title="">method
+      context</var>, with the <var title="">repeat</var> flag still set to true, and with the <var title="">previous handle</var> set to <var title="">handler</var>.</p>
 
-   <li><p>Let <var title="">timeout</var> be the second argument to the method, or zero if the
-   argument was omitted.</li>
+     </li>
 
-   <li><p>If <var title="">timeout</var> is less than 4, then increase <var title="">timeout</var>
-   to 4.</li> <!-- (but see note below about IE) -->
+    </ol></li>
 
+   <li><p>Let <var title="">timeout</var> be the second method argument, or zero if the argument was
+   omitted.</li>
+
+   <li><p>If the currently running <a href=#concept-task title=concept-task>task</a> is a task that was created
+   by this algorithm, then let <var title="">nesting level</var> be the <a href=#concept-task title=concept-task>task</a>'s <a href=#timer-nesting-level>timer nesting level</a>. Otherwise, let <var title="">nesting level</var> be zero.</li>
+
+   <li><p>If <var title="">nesting level</var> is greater than 5, and <var title="">timeout</var> is
+   less than 4, then increase <var title="">timeout</var> to 4.</li>
+
+   <li><p>Increment <var title="">nesting level</var> by one.</li>
+
+   <li><p>Let <var title="">task</var>'s <dfn id=timer-nesting-level>timer nesting level</dfn> be <var title="">nesting
+   level</var>.</li>
+
    <li><p>Return <var title="">handle</var>, and then continue running this algorithm
    asynchronously.</li>
 
-   <!-- Note: IE doesn't actually run intervals with duration zero, it aborts roughly here in the
-   algorithm for them. -->
-
    <li>
 
-    <p><i title="">Wait</i>: If the <a href=#method-context>method context</a> is a <code><a href=#window>Window</a></code> object,
-    wait until the <code><a href=#document>Document</a></code> associated with the <a href=#method-context>method context</a> has been
-    <a href=#fully-active>fully active</a> for a further <var title="">interval</var> milliseconds (not
-    necessarily consecutively).</p>
+    <p>If <var title="">method context</var> is a <code><a href=#window>Window</a></code> object, wait until the
+    <code><a href=#document>Document</a></code> associated with <var title="">method context</var> has been <a href=#fully-active>fully
+    active</a> for a further <var title="">timeout</var> milliseconds (not necessarily
+    consecutively).</p>
 
-    <p>Otherwise, if the <a href=#method-context>method context</a> is a <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object,
-    wait until <var title="">interval</var> milliseconds have passed with the worker not suspended
+    <p>Otherwise, <var title="">method context</var> is a <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object;
+    wait until <var title="">timeout</var> milliseconds have passed with the worker not suspended
     (not necessarily consecutively).</p>
 
-    <p>Otherwise, act as described in the specification that defines that the
-    <code><a href=#windowtimers>WindowTimers</a></code> interface is implemented by some other object.</p>
-
    </li>
 
    <li>
 
-    <p>Optionally, wait a further user-agent defined length of time.</p>
+    <p>Wait until any invocations of this algorithm that had the same <var title="">method
+    context</var>, that started before this one, and whose <var title="">timeout</var> is equal to
+    or less than this one's, have completed.</p>
 
-    <p class=note>This is intended to allow user agents to pad timeouts as needed to optimise the
-    power usage of the device. For example, some processors have a low-power mode where the
-    granularity of timers is reduced; on such platforms, user agents can slow timers down to fit
-    this schedule instead of requiring the processor to use the more accurate mode with its
-    associated higher power usage.</p>
+    <p class=note>Argument conversion as defined by Web IDL (for example, invoking <code title="">toString()</code> methods on objects passed as the first argument) happens in the
+    algorithms defined in Web IDL, before this algorithm is invoked.</p>
 
-   </li>
+    <div class=example>
 
-   <li><p><a href=#queue-a-task title="queue a task">Queue</a> the <var title="">task</var> <a href=#concept-task title=concept-task>task</a>.</li>
+     <p>So for example, the following rather silly code will result in the log containing "<code title="">ONE TWO </code>":</p>
 
-   <li><p>Return to the step labeled <i>wait</i>.</li>
+     <pre>var log = '';
+function logger(s) { log += s + ' '; }
 
-  </ol><hr><p>The <dfn id=dom-windowtimers-cleartimeout title=dom-windowtimers-clearTimeout><code>clearTimeout()</code></dfn> and <dfn id=dom-windowtimers-clearinterval title=dom-windowtimers-clearInterval><code>clearInterval()</code></dfn> methods must clear the
-  entry identified as <var title="">handle</var> from the <a href=#list-of-active-timers>list of active timers</a> of the
-  <code><a href=#windowtimers>WindowTimers</a></code> object on which the method was invoked, where <var title="">handle</var>
-  is the argument passed to the method, if any. (If <var title="">handle</var> does not identify an
-  entry in the <a href=#list-of-active-timers>list of active timers</a> of the <code><a href=#windowtimers>WindowTimers</a></code> object on which
-  the method was invoked, the method does nothing.)</p>
+setTimeout({ toString: function () {
+  setTimeout("logger('ONE')", 100);
+  return "logger('TWO')";
+} }, 100);</pre>
 
-  <hr><p>The <dfn id=method-context>method context</dfn>, when referenced by the algorithms in this section, is the object
-  on which the method for which the algorithm is running is implemented (a <code><a href=#window>Window</a></code> or
-  <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object). The <dfn id=method-context-proxy>method context proxy</dfn> is the <a href=#method-context>method
-  context</a> if that is a <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object, or else the
-  <code><a href=#windowproxy>WindowProxy</a></code> that corresponds to the <a href=#method-context>method context</a>.</p>
+    </div>
 
-  <p>When the above methods are invoked and try to <dfn id=get-the-timed-task>get the timed task</dfn> <var title="">handle</var> in list <var title="">list</var>, they must run the following steps:</p>
+   </li>
 
-  <ol><li>
+   <li>
 
-    <p>If the first argument to the invoked method is a <code>Function</code>, then return a <a href=#concept-task title=concept-task>task</a> that runs the following substeps, and then abort these steps:
+    <p>Optionally, wait a further user-agent defined length of time.</p>
 
-    <ol><li><p>If the entry for <var title="">handle</var> in <var title="">list</var> has been
-     cleared, then abort this <a href=#concept-task title=concept-task>task</a>'s substeps.</li>
+    <p class=note>This is intended to allow user agents to pad timeouts as needed to optimise the
+    power usage of the device. For example, some processors have a low-power mode where the
+    granularity of timers is reduced; on such platforms, user agents can slow timers down to fit
+    this schedule instead of requiring the processor to use the more accurate mode with its
+    associated higher power usage.</p>
 
-     <li>
+   </li>
 
-      <p>Call the <code>Function</code>. Use the third and subsequent arguments to the invoked
-      method (if any) as the arguments for invoking the <code>Function</code>. Use the <a href=#method-context-proxy>method
-      context proxy</a> as the <var title="">thisArg</var> for invoking the
-      <code>Function</code>. <a href=#refsECMA262>[ECMA262]</a></p>
+   <li>
 
-     </li>
+    <p><a href=#queue-a-task title="queue a task">Queue</a> the <a href=#concept-task title=concept-task>task</a> <var title="">task</var>.</p>
 
-    </ol><p>Otherwise, continue with the remaining steps.</p>
+    <p class=note>Once the task has been processed, if the <var title="">repeat</var> flag is
+    false, it is safe to remove the entry for <var title="">handle</var> from the <a href=#list-of-active-timers>list of
+    active timers</a> (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>Let <var title="">script source</var> be the first argument to the method.</li>
+  </ol><p>The <a href=#task-source>task source</a> for these <a href=#concept-task title=concept-task>tasks</a> is the
+  <dfn id=timer-task-source>timer task source</dfn>.</p>
 
-   <li><p>Let <var title="">script language</var> be JavaScript.</li>
+  </div>
 
-   <li>
+  <div class=example>
 
-    <p>If the <a href=#method-context>method context</a> is a <code><a href=#window>Window</a></code> object, let <var title="">global
-    object</var> be the <a href=#method-context>method context</a>, let <var title="">browsing context</var> be the
-    <a href=#browsing-context>browsing context</a> with which <var title="">global object</var> is associated, let
-    <var title="">document</var> and <var title="">referrer source</var> be the
-    <code><a href=#document>Document</a></code> associated with <var title="">global object</var>, let <var title="">character encoding</var> be the <a href="#document's-character-encoding" title="document's character encoding">character
-    encoding</a> of the <code><a href=#document>Document</a></code> associated with <var title="">global object</var>
-    (<a href=#sce-not-copy>this is a reference, not a copy</a>), and let <var title="">base
-    URL</var> be the <a href=#document-base-url title="document base URL">base URL</a> of the <code><a href=#document>Document</a></code>
-    associated with <var title="">global object</var> (<a href=#sbu-not-copy>this is a reference,
-    not a copy</a>).</p>
+   <p>To run tasks of several milliseconds back to back without any delay, while still yielding back
+   to the browser to avoid starving the user interface (and to avoid the browser killing the script
+   for hogging the CPU), simply queue the next timer before performing work:</p>
 
-    <p>Otherwise, if the <a href=#method-context>method context</a> is a <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object, let
-    <var title="">global object</var>, <var title="">browsing context</var>, <var title="">document</var>, <var title="">referrer source</var>, <var title="">character
-    encoding</var>, and <var title="">base URL</var> be the <a href="#script's-global-object">script's global object</a>,
-    <a href="#script's-browsing-context">script's browsing context</a>, <a href="#script's-document">script's document</a>, <a href="#script's-referrer-source">script's referrer
-    source</a>, <a href="#script's-url-character-encoding">script's URL character encoding</a>, and <a href="#script's-base-url">script's base URL</a>
-    (respectively) of the <a href=#concept-script title=concept-script>script</a> that the <a href=#run-a-worker>run a
-    worker</a> algorithm created when it created the <a href=#method-context>method context</a>.</p>
+   <pre>function doExpensiveWork() {
+  var done = false;
+  // ...
+  // this part of the function takes up to five milliseconds
+  // set done to true if we're done
+  // ...
+  return done;
+}
 
-    <p>Otherwise, act as described in the specification that defines that the
-    <code><a href=#windowtimers>WindowTimers</a></code> interface is implemented by some other object.</p>
+function rescheduleWork() {
+  var handle = setTimeout(rescheduleWork, 0); // preschedule next iteration
+  if (doExpensiveWork())
+    clearTimeout(handle); // clear the timeout if we don't need it
+}
 
-   </li>
+function scheduleWork() {
+  setTimeout(rescheduleWork, 0);
+}
 
-   <li><p>Return a <a href=#concept-task title=concept-task>task</a> that checks if the entry for <var title="">handle</var> in <var title="">list</var> has been cleared, and if it has not, <a href=#create-a-script title="create a script">creates a script</a> using <var title="">script source</var> as the
-   script source, the <a href=#url>URL</a> where <var title="">script source</var> can be found, <var title="">scripting language</var> as the scripting language, <var title="">global object</var> as
-   the global object, <var title="">browsing context</var> as the browsing context, <var title="">document</var> as the document, <var title="">referrer source</var> as the referrer
-   source, <var title="">character encoding</var> as the URL character encoding, and <var title="">base URL</var> as the base URL.</li>
+scheduleWork(); // queues a task to do lots of work</pre>
 
-  </ol><hr><p>The <a href=#task-source>task source</a> for these <a href=#concept-task title=concept-task>tasks</a> is the
-  <dfn id=timer-task-source>timer task source</dfn>.</p>
-
   </div>
 
 
-
   <h3 id=user-prompts><span class=secno>7.4 </span>User prompts</h3>
 
   <!--

Modified: index
===================================================================
--- index	2013-07-26 22:21:58 UTC (rev 8094)
+++ index	2013-07-26 23:27:44 UTC (rev 8095)
@@ -73252,7 +73252,10 @@
 
    </dd>
 
-  </dl><p class=note>This API does not guarantee that timers will run exactly on schedule. Delays due
+  </dl><p class=note>Timers can be nested; after five such nested timers, however, the interval is
+  forced to be at least four milliseconds.</p>
+
+  <p class=note>This API does not guarantee that timers will run exactly on schedule. Delays due
   to CPU load, other tasks, etc, are to be expected.</p>
 
   <div class=impl>
@@ -73264,229 +73267,230 @@
   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><a href=#windowtimers>WindowTimers</a></code> interface.</p>
 
-  <hr><p>The <dfn id=dom-windowtimers-settimeout title=dom-windowtimers-setTimeout><code>setTimeout()</code></dfn> method must run
-  the following steps:
+  <hr><p>The <dfn id=dom-windowtimers-settimeout title=dom-windowtimers-setTimeout><code>setTimeout()</code></dfn> method must return
+  the value returned by the <a href=#timer-initialization-steps>timer initialization steps</a>, passing them the method's
+  arguments, the object on which the method for which the algorithm is running is implemented (a
+  <code><a href=#window>Window</a></code> or <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object) as the <var title="">method
+  context</var>, and the <var title="">repeat</var> flag set to false.</p>
 
-  <ol><li><p>Let <var title="">handle</var> be a user-agent-defined integer that is greater than zero
-   that will identify the timeout to be set by this call in the <a href=#list-of-active-timers>list of active
-   timers</a>.</li>
+  <p>The <dfn id=dom-windowtimers-setinterval title=dom-windowtimers-setInterval><code>setInterval()</code></dfn> method must
+  return the value returned by the <a href=#timer-initialization-steps>timer initialization steps</a>, passing them the
+  method's arguments, the object on which the method for which the algorithm is running is
+  implemented (a <code><a href=#window>Window</a></code> or <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object) as the <var title="">method context</var>, and the <var title="">repeat</var> flag set to true.</p>
 
-   <li><p>Add an entry to the <a href=#list-of-active-timers>list of active timers</a> for <var title="">handle</var>.</li>
+  <p>The <dfn id=dom-windowtimers-cleartimeout title=dom-windowtimers-clearTimeout><code>clearTimeout()</code></dfn> and <dfn id=dom-windowtimers-clearinterval title=dom-windowtimers-clearInterval><code>clearInterval()</code></dfn> methods must clear the
+  entry identified as <var title="">handle</var> from the <a href=#list-of-active-timers>list of active timers</a> of the
+  <code><a href=#windowtimers>WindowTimers</a></code> object on which the method was invoked, where <var title="">handle</var>
+  is the argument passed to the method, if any. (If <var title="">handle</var> does not identify an
+  entry in the <a href=#list-of-active-timers>list of active timers</a> of the <code><a href=#windowtimers>WindowTimers</a></code> object on which
+  the method was invoked, the method does nothing.)</p>
 
-   <li><p><a href=#get-the-timed-task>Get the timed task</a> <var title="">handle</var> in the <a href=#list-of-active-timers>list of active
-   timers</a>, and let <var title="">task</var> be the result. This algorithm uses the first
-   argument to the method (<var title="">handler</var>) and, if there are any, the third and
-   subsequent arguments to the method (<var title="">arguments</var>), to establish precisely what
-   <var title="">task</var> does.</li>
+  <hr><p>The <dfn id=timer-initialization-steps>timer initialization steps</dfn>, which are invoked with some method arguments, a <var title="">method context</var>, a <var title="">repeat</var> flag which can be true or false, and
+  optionally (and only if the <var title="">repeat</var> flag is true) a <var title="">previous
+  handle</var>, are as follows:</p>
 
-   <li><p>Let <var title="">timeout</var> be the second argument to the method, or zero if the
-   argument was omitted.</li>
+  <ol><li><p>Let <var title="">method context proxy</var> be <var title="">method context</var> if that
+   is a <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object, or else the <code><a href=#windowproxy>WindowProxy</a></code> that corresponds
+   to <var title="">method context</var>.</li>
 
-   <li><p>If the currently running <a href=#concept-task title=concept-task>task</a> is a task that was created
-   by the <code title=dom-windowtimers-setTimeout><a href=#dom-windowtimers-settimeout>setTimeout()</a></code> method, and <var title="">timeout</var> is less than 4, then increase <var title="">timeout</var> to 4.</li>
+   <li><p>If <var title="">previous handle</var> was provided, let <var title="">handle</var> be
+   <var title="">previous handle</var>; otherwise, let <var title="">handle</var> be a
+   user-agent-defined integer that is greater than zero that will identify the timeout to be set by
+   this call in the <a href=#list-of-active-timers>list of active timers</a>.</li>
 
-   <li><p>Return <var title="">handle</var>, and then continue running this algorithm
-   asynchronously.</li>
+   <li><p>If <var title="">previous handle</var> was not provided, add an entry to the <a href=#list-of-active-timers>list of
+   active timers</a> for <var title="">handle</var>.</li>
 
    <li>
 
-    <p>If the <a href=#method-context>method context</a> is a <code><a href=#window>Window</a></code> object, wait until the
-    <code><a href=#document>Document</a></code> associated with the <a href=#method-context>method context</a> has been <a href=#fully-active>fully
-    active</a> for a further <var title="">timeout</var> milliseconds (not necessarily
-    consecutively).</p>
+    <p>Let <var title="">task</var> be a <a href=#concept-task title=concept-task>task</a> that runs the
+    following substeps:</p>
 
-    <p>Otherwise, if the <a href=#method-context>method context</a> is a <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object,
-    wait until <var title="">timeout</var> milliseconds have passed with the worker not suspended
-    (not necessarily consecutively).</p>
+    <ol><li>
 
-    <p>Otherwise, act as described in the specification that defines that the
-    <code><a href=#windowtimers>WindowTimers</a></code> interface is implemented by some other object.</p>
+      <p>If the entry for <var title="">handle</var> in the <a href=#list-of-active-timers>list of active timers</a> has
+      been cleared, then abort this <a href=#concept-task title=concept-task>task</a>'s substeps.</p>
 
-   </li>
+     </li>
 
-   <li>
+     <li>
 
-    <p>Wait until any invocations of this algorithm that had the same <a href=#method-context>method context</a>,
-    that started before this one, and whose <var title="">timeout</var> is equal to or less than
-    this one's, have completed.</p>
+      <p>Run the appropriate set of steps from the following list:</p>
 
-    <p class=note>Argument conversion as defined by Web IDL (for example, invoking <code title="">toString()</code> methods on objects passed as the first argument) happens in the
-    algorithms defined in Web IDL, before this algorithm is invoked.</p>
+      <dl class=switch><dt>If the first method argument is a <code>Function</code></dt>
 
-    <div class=example>
+       <dd>
 
-     <p>So for example, the following rather silly code will result in the log containing "<code title="">ONE TWO </code>":</p>
+        <p>Call the <code>Function</code>. Use the third and subsequent method arguments (if any) as
+        the arguments for invoking the <code>Function</code>. Use <var title="">method context
+        proxy</var> as the <var title="">thisArg</var> for invoking the <code>Function</code>. <a href=#refsECMA262>[ECMA262]</a></p>
 
-     <pre>var log = '';
-function logger(s) { log += s + ' '; }
+       </dd>
 
-setTimeout({ toString: function () {
-  setTimeout("logger('ONE')", 100);
-  return "logger('TWO')";
-} }, 100);</pre>
+       <dt>Otherwise</dt>
 
-    </div>
+       <dd>
 
-   </li>
+        <ol><li><p>Let <var title="">script source</var> be the first method argument.</li>
 
-   <li>
+         <li><p>Let <var title="">script language</var> be JavaScript.</li>
 
-    <p>Optionally, wait a further user-agent defined length of time.</p>
+         <li>
 
-    <p class=note>This is intended to allow user agents to pad timeouts as needed to optimise the
-    power usage of the device. For example, some processors have a low-power mode where the
-    granularity of timers is reduced; on such platforms, user agents can slow timers down to fit
-    this schedule instead of requiring the processor to use the more accurate mode with its
-    associated higher power usage.</p>
+          <p>If <var title="">method context</var> is a <code><a href=#window>Window</a></code> object, let <var title="">global object</var> be <var title="">method context</var>, let <var title="">browsing context</var> be the <a href=#browsing-context>browsing context</a> with which <var title="">global object</var> is associated, let <var title="">document</var> and <var title="">referrer source</var> be the <code><a href=#document>Document</a></code> associated with <var title="">global object</var>, let <var title="">character encoding</var> be the <a href="#document's-character-encoding" title="document's character encoding">character encoding</a> of the <code><a href=#document>Document</a></code>
+          associated with <var title="">global object</var> (<a href=#sce-not-copy>this is a
+          reference, not a copy</a>), and let <var title="">base URL</var> be the <a href=#document-base-url title="document base URL">base URL</a> of the <code><a href=#document>Document</a></code> associated with <var title="">global object</var> (<a href=#sbu-not-copy>this is a reference, not a
+          copy</a>).</p>
 
-   </li>
+          <p>Otherwise, <var title="">method context</var> is a <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object;
+          let <var title="">global object</var>, <var title="">browsing context</var>, <var title="">document</var>, <var title="">referrer source</var>, <var title="">character
+          encoding</var>, and <var title="">base URL</var> be the <a href="#script's-global-object">script's global object</a>,
+          <a href="#script's-browsing-context">script's browsing context</a>, <a href="#script's-document">script's document</a>, <a href="#script's-referrer-source">script's
+          referrer source</a>, <a href="#script's-url-character-encoding">script's URL character encoding</a>, and <a href="#script's-base-url">script's
+          base URL</a> (respectively) of the <a href=#concept-script title=concept-script>script</a> that the
+          <a href=#run-a-worker>run a worker</a> algorithm created when it created <var title="">method
+          context</var>.</p>
 
-   <li>
+         </li>
 
-    <p><a href=#queue-a-task title="queue a task">Queue</a> the <a href=#concept-task title=concept-task>task</a> <var title="">task</var>.</p>
+         <li>
 
-    <p class=note>Once the task has been processed, it is safe to remove the entry for <var title="">handle</var> from the <a href=#list-of-active-timers>list of active timers</a> (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>
+          <p><a href=#create-a-script>Create a script</a> using <var title="">script source</var> as the script
+          source, the <a href=#url>URL</a> where <var title="">script source</var> can be found, <var title="">scripting language</var> as the scripting language, <var title="">global
+          object</var> as the global object, <var title="">browsing context</var> as the browsing
+          context, <var title="">document</var> as the document, <var title="">referrer source</var>
+          as the referrer source, <var title="">character encoding</var> as the URL character
+          encoding, and <var title="">base URL</var> as the base URL.</p>
 
-   </li>
+         </li>
 
-  </ol><hr><p>The <dfn id=dom-windowtimers-setinterval title=dom-windowtimers-setInterval><code>setInterval()</code></dfn> method must run
-  the following steps:
+        </ol></dd>
 
-  <ol><li><p>Let <var title="">handle</var> be a user-agent-defined integer that is greater than zero
-   that will identify the timeout to be set by this call in the <a href=#list-of-active-timers>list of active
-   timers</a>.</li>
+      </dl></li>
 
-   <li><p>Add an entry to the <a href=#list-of-active-timers>list of active timers</a> for <var title="">handle</var>.</li>
+     <li>
 
-   <li><p><a href=#get-the-timed-task>Get the timed task</a> <var title="">handle</var> in the <a href=#list-of-active-timers>list of active
-   timers</a>, and let <var title="">task</var> be the result. This algorithm uses the first
-   argument to the method (<var title="">handler</var>) and, if there are any, the third and
-   subsequent arguments to the method (<var title="">arguments</var>), to establish precisely what
-   <var title="">task</var> does.</li>
+      <p>If the <var title="">repeat</var> flag is true, then call <a href=#timer-initialization-steps>timer initialization
+      steps</a> again, passing them the same method arguments, the same <var title="">method
+      context</var>, with the <var title="">repeat</var> flag still set to true, and with the <var title="">previous handle</var> set to <var title="">handler</var>.</p>
 
-   <li><p>Let <var title="">timeout</var> be the second argument to the method, or zero if the
-   argument was omitted.</li>
+     </li>
 
-   <li><p>If <var title="">timeout</var> is less than 4, then increase <var title="">timeout</var>
-   to 4.</li> <!-- (but see note below about IE) -->
+    </ol></li>
 
+   <li><p>Let <var title="">timeout</var> be the second method argument, or zero if the argument was
+   omitted.</li>
+
+   <li><p>If the currently running <a href=#concept-task title=concept-task>task</a> is a task that was created
+   by this algorithm, then let <var title="">nesting level</var> be the <a href=#concept-task title=concept-task>task</a>'s <a href=#timer-nesting-level>timer nesting level</a>. Otherwise, let <var title="">nesting level</var> be zero.</li>
+
+   <li><p>If <var title="">nesting level</var> is greater than 5, and <var title="">timeout</var> is
+   less than 4, then increase <var title="">timeout</var> to 4.</li>
+
+   <li><p>Increment <var title="">nesting level</var> by one.</li>
+
+   <li><p>Let <var title="">task</var>'s <dfn id=timer-nesting-level>timer nesting level</dfn> be <var title="">nesting
+   level</var>.</li>
+
    <li><p>Return <var title="">handle</var>, and then continue running this algorithm
    asynchronously.</li>
 
-   <!-- Note: IE doesn't actually run intervals with duration zero, it aborts roughly here in the
-   algorithm for them. -->
-
    <li>
 
-    <p><i title="">Wait</i>: If the <a href=#method-context>method context</a> is a <code><a href=#window>Window</a></code> object,
-    wait until the <code><a href=#document>Document</a></code> associated with the <a href=#method-context>method context</a> has been
-    <a href=#fully-active>fully active</a> for a further <var title="">interval</var> milliseconds (not
-    necessarily consecutively).</p>
+    <p>If <var title="">method context</var> is a <code><a href=#window>Window</a></code> object, wait until the
+    <code><a href=#document>Document</a></code> associated with <var title="">method context</var> has been <a href=#fully-active>fully
+    active</a> for a further <var title="">timeout</var> milliseconds (not necessarily
+    consecutively).</p>
 
-    <p>Otherwise, if the <a href=#method-context>method context</a> is a <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object,
-    wait until <var title="">interval</var> milliseconds have passed with the worker not suspended
+    <p>Otherwise, <var title="">method context</var> is a <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object;
+    wait until <var title="">timeout</var> milliseconds have passed with the worker not suspended
     (not necessarily consecutively).</p>
 
-    <p>Otherwise, act as described in the specification that defines that the
-    <code><a href=#windowtimers>WindowTimers</a></code> interface is implemented by some other object.</p>
-
    </li>
 
    <li>
 
-    <p>Optionally, wait a further user-agent defined length of time.</p>
+    <p>Wait until any invocations of this algorithm that had the same <var title="">method
+    context</var>, that started before this one, and whose <var title="">timeout</var> is equal to
+    or less than this one's, have completed.</p>
 
-    <p class=note>This is intended to allow user agents to pad timeouts as needed to optimise the
-    power usage of the device. For example, some processors have a low-power mode where the
-    granularity of timers is reduced; on such platforms, user agents can slow timers down to fit
-    this schedule instead of requiring the processor to use the more accurate mode with its
-    associated higher power usage.</p>
+    <p class=note>Argument conversion as defined by Web IDL (for example, invoking <code title="">toString()</code> methods on objects passed as the first argument) happens in the
+    algorithms defined in Web IDL, before this algorithm is invoked.</p>
 
-   </li>
+    <div class=example>
 
-   <li><p><a href=#queue-a-task title="queue a task">Queue</a> the <var title="">task</var> <a href=#concept-task title=concept-task>task</a>.</li>
+     <p>So for example, the following rather silly code will result in the log containing "<code title="">ONE TWO </code>":</p>
 
-   <li><p>Return to the step labeled <i>wait</i>.</li>
+     <pre>var log = '';
+function logger(s) { log += s + ' '; }
 
-  </ol><hr><p>The <dfn id=dom-windowtimers-cleartimeout title=dom-windowtimers-clearTimeout><code>clearTimeout()</code></dfn> and <dfn id=dom-windowtimers-clearinterval title=dom-windowtimers-clearInterval><code>clearInterval()</code></dfn> methods must clear the
-  entry identified as <var title="">handle</var> from the <a href=#list-of-active-timers>list of active timers</a> of the
-  <code><a href=#windowtimers>WindowTimers</a></code> object on which the method was invoked, where <var title="">handle</var>
-  is the argument passed to the method, if any. (If <var title="">handle</var> does not identify an
-  entry in the <a href=#list-of-active-timers>list of active timers</a> of the <code><a href=#windowtimers>WindowTimers</a></code> object on which
-  the method was invoked, the method does nothing.)</p>
+setTimeout({ toString: function () {
+  setTimeout("logger('ONE')", 100);
+  return "logger('TWO')";
+} }, 100);</pre>
 
-  <hr><p>The <dfn id=method-context>method context</dfn>, when referenced by the algorithms in this section, is the object
-  on which the method for which the algorithm is running is implemented (a <code><a href=#window>Window</a></code> or
-  <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object). The <dfn id=method-context-proxy>method context proxy</dfn> is the <a href=#method-context>method
-  context</a> if that is a <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object, or else the
-  <code><a href=#windowproxy>WindowProxy</a></code> that corresponds to the <a href=#method-context>method context</a>.</p>
+    </div>
 
-  <p>When the above methods are invoked and try to <dfn id=get-the-timed-task>get the timed task</dfn> <var title="">handle</var> in list <var title="">list</var>, they must run the following steps:</p>
+   </li>
 
-  <ol><li>
+   <li>
 
-    <p>If the first argument to the invoked method is a <code>Function</code>, then return a <a href=#concept-task title=concept-task>task</a> that runs the following substeps, and then abort these steps:
+    <p>Optionally, wait a further user-agent defined length of time.</p>
 
-    <ol><li><p>If the entry for <var title="">handle</var> in <var title="">list</var> has been
-     cleared, then abort this <a href=#concept-task title=concept-task>task</a>'s substeps.</li>
+    <p class=note>This is intended to allow user agents to pad timeouts as needed to optimise the
+    power usage of the device. For example, some processors have a low-power mode where the
+    granularity of timers is reduced; on such platforms, user agents can slow timers down to fit
+    this schedule instead of requiring the processor to use the more accurate mode with its
+    associated higher power usage.</p>
 
-     <li>
+   </li>
 
-      <p>Call the <code>Function</code>. Use the third and subsequent arguments to the invoked
-      method (if any) as the arguments for invoking the <code>Function</code>. Use the <a href=#method-context-proxy>method
-      context proxy</a> as the <var title="">thisArg</var> for invoking the
-      <code>Function</code>. <a href=#refsECMA262>[ECMA262]</a></p>
+   <li>
 
-     </li>
+    <p><a href=#queue-a-task title="queue a task">Queue</a> the <a href=#concept-task title=concept-task>task</a> <var title="">task</var>.</p>
 
-    </ol><p>Otherwise, continue with the remaining steps.</p>
+    <p class=note>Once the task has been processed, if the <var title="">repeat</var> flag is
+    false, it is safe to remove the entry for <var title="">handle</var> from the <a href=#list-of-active-timers>list of
+    active timers</a> (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>Let <var title="">script source</var> be the first argument to the method.</li>
+  </ol><p>The <a href=#task-source>task source</a> for these <a href=#concept-task title=concept-task>tasks</a> is the
+  <dfn id=timer-task-source>timer task source</dfn>.</p>
 
-   <li><p>Let <var title="">script language</var> be JavaScript.</li>
+  </div>
 
-   <li>
+  <div class=example>
 
-    <p>If the <a href=#method-context>method context</a> is a <code><a href=#window>Window</a></code> object, let <var title="">global
-    object</var> be the <a href=#method-context>method context</a>, let <var title="">browsing context</var> be the
-    <a href=#browsing-context>browsing context</a> with which <var title="">global object</var> is associated, let
-    <var title="">document</var> and <var title="">referrer source</var> be the
-    <code><a href=#document>Document</a></code> associated with <var title="">global object</var>, let <var title="">character encoding</var> be the <a href="#document's-character-encoding" title="document's character encoding">character
-    encoding</a> of the <code><a href=#document>Document</a></code> associated with <var title="">global object</var>
-    (<a href=#sce-not-copy>this is a reference, not a copy</a>), and let <var title="">base
-    URL</var> be the <a href=#document-base-url title="document base URL">base URL</a> of the <code><a href=#document>Document</a></code>
-    associated with <var title="">global object</var> (<a href=#sbu-not-copy>this is a reference,
-    not a copy</a>).</p>
+   <p>To run tasks of several milliseconds back to back without any delay, while still yielding back
+   to the browser to avoid starving the user interface (and to avoid the browser killing the script
+   for hogging the CPU), simply queue the next timer before performing work:</p>
 
-    <p>Otherwise, if the <a href=#method-context>method context</a> is a <code><a href=#workerglobalscope>WorkerGlobalScope</a></code> object, let
-    <var title="">global object</var>, <var title="">browsing context</var>, <var title="">document</var>, <var title="">referrer source</var>, <var title="">character
-    encoding</var>, and <var title="">base URL</var> be the <a href="#script's-global-object">script's global object</a>,
-    <a href="#script's-browsing-context">script's browsing context</a>, <a href="#script's-document">script's document</a>, <a href="#script's-referrer-source">script's referrer
-    source</a>, <a href="#script's-url-character-encoding">script's URL character encoding</a>, and <a href="#script's-base-url">script's base URL</a>
-    (respectively) of the <a href=#concept-script title=concept-script>script</a> that the <a href=#run-a-worker>run a
-    worker</a> algorithm created when it created the <a href=#method-context>method context</a>.</p>
+   <pre>function doExpensiveWork() {
+  var done = false;
+  // ...
+  // this part of the function takes up to five milliseconds
+  // set done to true if we're done
+  // ...
+  return done;
+}
 
-    <p>Otherwise, act as described in the specification that defines that the
-    <code><a href=#windowtimers>WindowTimers</a></code> interface is implemented by some other object.</p>
+function rescheduleWork() {
+  var handle = setTimeout(rescheduleWork, 0); // preschedule next iteration
+  if (doExpensiveWork())
+    clearTimeout(handle); // clear the timeout if we don't need it
+}
 
-   </li>
+function scheduleWork() {
+  setTimeout(rescheduleWork, 0);
+}
 
-   <li><p>Return a <a href=#concept-task title=concept-task>task</a> that checks if the entry for <var title="">handle</var> in <var title="">list</var> has been cleared, and if it has not, <a href=#create-a-script title="create a script">creates a script</a> using <var title="">script source</var> as the
-   script source, the <a href=#url>URL</a> where <var title="">script source</var> can be found, <var title="">scripting language</var> as the scripting language, <var title="">global object</var> as
-   the global object, <var title="">browsing context</var> as the browsing context, <var title="">document</var> as the document, <var title="">referrer source</var> as the referrer
-   source, <var title="">character encoding</var> as the URL character encoding, and <var title="">base URL</var> as the base URL.</li>
+scheduleWork(); // queues a task to do lots of work</pre>
 
-  </ol><hr><p>The <a href=#task-source>task source</a> for these <a href=#concept-task title=concept-task>tasks</a> is the
-  <dfn id=timer-task-source>timer task source</dfn>.</p>
-
   </div>
 
 
-
   <h3 id=user-prompts><span class=secno>7.4 </span>User prompts</h3>
 
   <!--

Modified: source
===================================================================
--- source	2013-07-26 22:21:58 UTC (rev 8094)
+++ source	2013-07-26 23:27:44 UTC (rev 8095)
@@ -81983,6 +81983,9 @@
 
   </dl>
 
+  <p class="note">Timers can be nested; after five such nested timers, however, the interval is
+  forced to be at least four milliseconds.</p>
+
   <p class="note">This API does not guarantee that timers will run exactly on schedule. Delays due
   to CPU load, other tasks, etc, are to be expected.</p>
 
@@ -81997,271 +82000,268 @@
 
   <hr>
 
-  <p>The <dfn title="dom-windowtimers-setTimeout"><code>setTimeout()</code></dfn> method must run
-  the following steps:
+  <p>The <dfn title="dom-windowtimers-setTimeout"><code>setTimeout()</code></dfn> method must return
+  the value returned by the <span>timer initialization steps</span>, passing them the method's
+  arguments, the object on which the method for which the algorithm is running is implemented (a
+  <code>Window</code> or <code>WorkerGlobalScope</code> object) as the <var title="">method
+  context</var>, and the <var title="">repeat</var> flag set to false.</p>
 
-  <ol>
+  <p>The <dfn title="dom-windowtimers-setInterval"><code>setInterval()</code></dfn> method must
+  return the value returned by the <span>timer initialization steps</span>, passing them the
+  method's arguments, the object on which the method for which the algorithm is running is
+  implemented (a <code>Window</code> or <code>WorkerGlobalScope</code> object) as the <var
+  title="">method context</var>, and the <var title="">repeat</var> flag set to true.</p>
 
-   <li><p>Let <var title="">handle</var> be a user-agent-defined integer that is greater than zero
-   that will identify the timeout to be set by this call in the <span>list of active
-   timers</span>.</p></li>
+  <p>The <dfn title="dom-windowtimers-clearTimeout"><code>clearTimeout()</code></dfn> and <dfn
+  title="dom-windowtimers-clearInterval"><code>clearInterval()</code></dfn> methods must clear the
+  entry identified as <var title="">handle</var> from the <span>list of active timers</span> of the
+  <code>WindowTimers</code> object on which the method was invoked, where <var title="">handle</var>
+  is the argument passed to the method, if any. (If <var title="">handle</var> does not identify an
+  entry in the <span>list of active timers</span> of the <code>WindowTimers</code> object on which
+  the method was invoked, the method does nothing.)</p>
 
-   <li><p>Add an entry to the <span>list of active timers</span> for <var
-   title="">handle</var>.</p></li>
+  <hr>
 
-   <li><p><span>Get the timed task</span> <var title="">handle</var> in the <span>list of active
-   timers</span>, and let <var title="">task</var> be the result. This algorithm uses the first
-   argument to the method (<var title="">handler</var>) and, if there are any, the third and
-   subsequent arguments to the method (<var title="">arguments</var>), to establish precisely what
-   <var title="">task</var> does.</p></li>
+  <p>The <dfn>timer initialization steps</dfn>, which are invoked with some method arguments, a <var
+  title="">method context</var>, a <var title="">repeat</var> flag which can be true or false, and
+  optionally (and only if the <var title="">repeat</var> flag is true) a <var title="">previous
+  handle</var>, are as follows:</p>
 
-   <li><p>Let <var title="">timeout</var> be the second argument to the method, or zero if the
-   argument was omitted.</p></li>
+  <ol>
 
-   <li><p>If the currently running <span title="concept-task">task</span> is a task that was created
-   by the <code title="dom-windowtimers-setTimeout">setTimeout()</code> method, and <var
-   title="">timeout</var> is less than 4, then increase <var title="">timeout</var> to 4.</p></li>
+   <li><p>Let <var title="">method context proxy</var> be <var title="">method context</var> if that
+   is a <code>WorkerGlobalScope</code> object, or else the <code>WindowProxy</code> that corresponds
+   to <var title="">method context</var>.</p></li>
 
-   <li><p>Return <var title="">handle</var>, and then continue running this algorithm
-   asynchronously.</p></li>
+   <li><p>If <var title="">previous handle</var> was provided, let <var title="">handle</var> be
+   <var title="">previous handle</var>; otherwise, let <var title="">handle</var> be a
+   user-agent-defined integer that is greater than zero that will identify the timeout to be set by
+   this call in the <span>list of active timers</span>.</p></li>
 
+   <li><p>If <var title="">previous handle</var> was not provided, add an entry to the <span>list of
+   active timers</span> for <var title="">handle</var>.</p></li>
+
    <li>
 
-    <p>If the <span>method context</span> is a <code>Window</code> object, wait until the
-    <code>Document</code> associated with the <span>method context</span> has been <span>fully
-    active</span> for a further <var title="">timeout</var> milliseconds (not necessarily
-    consecutively).</p>
+    <p>Let <var title="">task</var> be a <span title="concept-task">task</span> that runs the
+    following substeps:</p>
 
-    <p>Otherwise, if the <span>method context</span> is a <code>WorkerGlobalScope</code> object,
-    wait until <var title="">timeout</var> milliseconds have passed with the worker not suspended
-    (not necessarily consecutively).</p>
+    <ol>
 
-    <p>Otherwise, act as described in the specification that defines that the
-    <code>WindowTimers</code> interface is implemented by some other object.</p>
+     <li>
 
-   </li>
+      <p>If the entry for <var title="">handle</var> in the <span>list of active timers</span> has
+      been cleared, then abort this <span title="concept-task">task</span>'s substeps.</p>
 
-   <li>
+     </li>
 
-    <p>Wait until any invocations of this algorithm that had the same <span>method context</span>,
-    that started before this one, and whose <var title="">timeout</var> is equal to or less than
-    this one's, have completed.</p>
+     <li>
 
-    <p class="note">Argument conversion as defined by Web IDL (for example, invoking <code
-    title="">toString()</code> methods on objects passed as the first argument) happens in the
-    algorithms defined in Web IDL, before this algorithm is invoked.</p>
+      <p>Run the appropriate set of steps from the following list:</p>
 
-    <div class="example">
+      <dl class="switch">
 
-     <p>So for example, the following rather silly code will result in the log containing "<code
-     title="">ONE TWO </code>":</p>
+       <dt>If the first method argument is a <code>Function</code></dt>
 
-     <pre>var log = '';
-function logger(s) { log += s + ' '; }
+       <dd>
 
-setTimeout({ toString: function () {
-  setTimeout("logger('ONE')", 100);
-  return "logger('TWO')";
-} }, 100);</pre>
+        <p>Call the <code>Function</code>. Use the third and subsequent method arguments (if any) as
+        the arguments for invoking the <code>Function</code>. Use <var title="">method context
+        proxy</var> as the <var title="">thisArg</var> for invoking the <code>Function</code>. <a
+        href="#refsECMA262">[ECMA262]</a></p>
 
-    </div>
+       </dd>
 
-   </li>
+       <dt>Otherwise</dt>
 
-   <li>
+       <dd>
 
-    <p>Optionally, wait a further user-agent defined length of time.</p>
+        <ol>
 
-    <p class="note">This is intended to allow user agents to pad timeouts as needed to optimise the
-    power usage of the device. For example, some processors have a low-power mode where the
-    granularity of timers is reduced; on such platforms, user agents can slow timers down to fit
-    this schedule instead of requiring the processor to use the more accurate mode with its
-    associated higher power usage.</p>
+         <li><p>Let <var title="">script source</var> be the first method argument.</p></li>
 
-   </li>
+         <li><p>Let <var title="">script language</var> be JavaScript.</p></li>
 
-   <li>
+         <li>
 
-    <p><span title="queue a task">Queue</span> the <span title="concept-task">task</span> <var
-    title="">task</var>.</p>
+          <p>If <var title="">method context</var> is a <code>Window</code> object, let <var
+          title="">global object</var> be <var title="">method context</var>, let <var
+          title="">browsing context</var> be the <span>browsing context</span> with which <var
+          title="">global object</var> is associated, let <var title="">document</var> and <var
+          title="">referrer source</var> be the <code>Document</code> associated with <var
+          title="">global object</var>, let <var title="">character encoding</var> be the <span
+          title="document's character encoding">character encoding</span> of the <code>Document</code>
+          associated with <var title="">global object</var> (<a href="#sce-not-copy">this is a
+          reference, not a copy</a>), and let <var title="">base URL</var> be the <span
+          title="document base URL">base URL</span> of the <code>Document</code> associated with <var
+          title="">global object</var> (<a href="#sbu-not-copy">this is a reference, not a
+          copy</a>).</p>
 
-    <p class="note">Once the task has been processed, it is safe to remove the entry for <var
-    title="">handle</var> from the <span>list 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>
+          <p>Otherwise, <var title="">method context</var> is a <code>WorkerGlobalScope</code> object;
+          let <var title="">global object</var>, <var title="">browsing context</var>, <var
+          title="">document</var>, <var title="">referrer source</var>, <var title="">character
+          encoding</var>, and <var title="">base URL</var> be the <span>script's global object</span>,
+          <span>script's browsing context</span>, <span>script's document</span>, <span>script's
+          referrer source</span>, <span>script's URL character encoding</span>, and <span>script's
+          base URL</span> (respectively) of the <span title="concept-script">script</span> that the
+          <span>run a worker</span> algorithm created when it created <var title="">method
+          context</var>.</p>
 
-   </li>
+         </li>
 
-  </ol>
+         <li>
 
-  <hr>
+          <p><span>Create a script</span> using <var title="">script source</var> as the script
+          source, the <span>URL</span> where <var title="">script source</var> can be found, <var
+          title="">scripting language</var> as the scripting language, <var title="">global
+          object</var> as the global object, <var title="">browsing context</var> as the browsing
+          context, <var title="">document</var> as the document, <var title="">referrer source</var>
+          as the referrer source, <var title="">character encoding</var> as the URL character
+          encoding, and <var title="">base URL</var> as the base URL.</p>
 
-  <p>The <dfn title="dom-windowtimers-setInterval"><code>setInterval()</code></dfn> method must run
-  the following steps:
+         </li>
 
-  <ol>
+        </ol>
 
-   <li><p>Let <var title="">handle</var> be a user-agent-defined integer that is greater than zero
-   that will identify the timeout to be set by this call in the <span>list of active
-   timers</span>.</p></li>
+       </dd>
 
-   <li><p>Add an entry to the <span>list of active timers</span> for <var
-   title="">handle</var>.</p></li>
+      </dl>
 
-   <li><p><span>Get the timed task</span> <var title="">handle</var> in the <span>list of active
-   timers</span>, and let <var title="">task</var> be the result. This algorithm uses the first
-   argument to the method (<var title="">handler</var>) and, if there are any, the third and
-   subsequent arguments to the method (<var title="">arguments</var>), to establish precisely what
-   <var title="">task</var> does.</p></li>
+     </li>
 
-   <li><p>Let <var title="">timeout</var> be the second argument to the method, or zero if the
-   argument was omitted.</p></li>
+     <li>
 
-   <li><p>If <var title="">timeout</var> is less than 4, then increase <var title="">timeout</var>
-   to 4.</p></li> <!-- (but see note below about IE) -->
+      <p>If the <var title="">repeat</var> flag is true, then call <span>timer initialization
+      steps</span> again, passing them the same method arguments, the same <var title="">method
+      context</var>, with the <var title="">repeat</var> flag still set to true, and with the <var
+      title="">previous handle</var> set to <var title="">handler</var>.</p>
 
-   <li><p>Return <var title="">handle</var>, and then continue running this algorithm
-   asynchronously.</p></li>
+     </li>
 
-   <!-- Note: IE doesn't actually run intervals with duration zero, it aborts roughly here in the
-   algorithm for them. -->
+    </ol>
 
-   <li>
+   </li>
 
-    <p><i title="">Wait</i>: If the <span>method context</span> is a <code>Window</code> object,
-    wait until the <code>Document</code> associated with the <span>method context</span> has been
-    <span>fully active</span> for a further <var title="">interval</var> milliseconds (not
-    necessarily consecutively).</p>
+   <li><p>Let <var title="">timeout</var> be the second method argument, or zero if the argument was
+   omitted.</p></li>
 
-    <p>Otherwise, if the <span>method context</span> is a <code>WorkerGlobalScope</code> object,
-    wait until <var title="">interval</var> milliseconds have passed with the worker not suspended
-    (not necessarily consecutively).</p>
+   <li><p>If the currently running <span title="concept-task">task</span> is a task that was created
+   by this algorithm, then let <var title="">nesting level</var> be the <span
+   title="concept-task">task</span>'s <span>timer nesting level</span>. Otherwise, let <var
+   title="">nesting level</var> be zero.</p></li>
 
-    <p>Otherwise, act as described in the specification that defines that the
-    <code>WindowTimers</code> interface is implemented by some other object.</p>
+   <li><p>If <var title="">nesting level</var> is greater than 5, and <var title="">timeout</var> is
+   less than 4, then increase <var title="">timeout</var> to 4.</p></li>
 
-   </li>
+   <li><p>Increment <var title="">nesting level</var> by one.</p></li>
 
+   <li><p>Let <var title="">task</var>'s <dfn>timer nesting level</dfn> be <var title="">nesting
+   level</var>.</p></li>
+
+   <li><p>Return <var title="">handle</var>, and then continue running this algorithm
+   asynchronously.</p></li>
+
    <li>
 
-    <p>Optionally, wait a further user-agent defined length of time.</p>
+    <p>If <var title="">method context</var> is a <code>Window</code> object, wait until the
+    <code>Document</code> associated with <var title="">method context</var> has been <span>fully
+    active</span> for a further <var title="">timeout</var> milliseconds (not necessarily
+    consecutively).</p>
 
-    <p class="note">This is intended to allow user agents to pad timeouts as needed to optimise the
-    power usage of the device. For example, some processors have a low-power mode where the
-    granularity of timers is reduced; on such platforms, user agents can slow timers down to fit
-    this schedule instead of requiring the processor to use the more accurate mode with its
-    associated higher power usage.</p>
+    <p>Otherwise, <var title="">method context</var> is a <code>WorkerGlobalScope</code> object;
+    wait until <var title="">timeout</var> milliseconds have passed with the worker not suspended
+    (not necessarily consecutively).</p>
 
    </li>
 
-   <li><p><span title="queue a task">Queue</span> the <var title="">task</var> <span
-   title="concept-task">task</span>.</p></li>
+   <li>
 
-   <li><p>Return to the step labeled <i>wait</i>.</p></li>
+    <p>Wait until any invocations of this algorithm that had the same <var title="">method
+    context</var>, that started before this one, and whose <var title="">timeout</var> is equal to
+    or less than this one's, have completed.</p>
 
-  </ol>
+    <p class="note">Argument conversion as defined by Web IDL (for example, invoking <code
+    title="">toString()</code> methods on objects passed as the first argument) happens in the
+    algorithms defined in Web IDL, before this algorithm is invoked.</p>
 
-  <hr>
+    <div class="example">
 
-  <p>The <dfn title="dom-windowtimers-clearTimeout"><code>clearTimeout()</code></dfn> and <dfn
-  title="dom-windowtimers-clearInterval"><code>clearInterval()</code></dfn> methods must clear the
-  entry identified as <var title="">handle</var> from the <span>list of active timers</span> of the
-  <code>WindowTimers</code> object on which the method was invoked, where <var title="">handle</var>
-  is the argument passed to the method, if any. (If <var title="">handle</var> does not identify an
-  entry in the <span>list of active timers</span> of the <code>WindowTimers</code> object on which
-  the method was invoked, the method does nothing.)</p>
+     <p>So for example, the following rather silly code will result in the log containing "<code
+     title="">ONE TWO </code>":</p>
 
-  <hr>
+     <pre>var log = '';
+function logger(s) { log += s + ' '; }
 
-  <p>The <dfn>method context</dfn>, when referenced by the algorithms in this section, is the object
-  on which the method for which the algorithm is running is implemented (a <code>Window</code> or
-  <code>WorkerGlobalScope</code> object). The <dfn>method context proxy</dfn> is the <span>method
-  context</span> if that is a <code>WorkerGlobalScope</code> object, or else the
-  <code>WindowProxy</code> that corresponds to the <span>method context</span>.</p>
+setTimeout({ toString: function () {
+  setTimeout("logger('ONE')", 100);
+  return "logger('TWO')";
+} }, 100);</pre>
 
-  <p>When the above methods are invoked and try to <dfn>get the timed task</dfn> <var
-  title="">handle</var> in list <var title="">list</var>, they must run the following steps:</p>
+    </div>
 
-  <ol>
+   </li>
 
    <li>
 
-    <p>If the first argument to the invoked method is a <code>Function</code>, then return a <span
-    title="concept-task">task</span> that runs the following substeps, and then abort these steps:
+    <p>Optionally, wait a further user-agent defined length of time.</p>
 
-    <ol>
+    <p class="note">This is intended to allow user agents to pad timeouts as needed to optimise the
+    power usage of the device. For example, some processors have a low-power mode where the
+    granularity of timers is reduced; on such platforms, user agents can slow timers down to fit
+    this schedule instead of requiring the processor to use the more accurate mode with its
+    associated higher power usage.</p>
 
-     <li><p>If the entry for <var title="">handle</var> in <var title="">list</var> has been
-     cleared, then abort this <span title="concept-task">task</span>'s substeps.</p></li>
+   </li>
 
-     <li>
+   <li>
 
-      <p>Call the <code>Function</code>. Use the third and subsequent arguments to the invoked
-      method (if any) as the arguments for invoking the <code>Function</code>. Use the <span>method
-      context proxy</span> as the <var title="">thisArg</var> for invoking the
-      <code>Function</code>. <a href="#refsECMA262">[ECMA262]</a></p>
+    <p><span title="queue a task">Queue</span> the <span title="concept-task">task</span> <var
+    title="">task</var>.</p>
 
-     </li>
+    <p class="note">Once the task has been processed, if the <var title="">repeat</var> flag is
+    false, it is safe to remove the entry for <var title="">handle</var> from the <span>list 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>
 
-    </ol>
-
-    <p>Otherwise, continue with the remaining steps.</p>
-
    </li>
 
-   <li><p>Let <var title="">script source</var> be the first argument to the method.</p></li>
+  </ol>
 
-   <li><p>Let <var title="">script language</var> be JavaScript.</p></li>
+  <p>The <span>task source</span> for these <span title="concept-task">tasks</span> is the
+  <dfn>timer task source</dfn>.</p>
 
-   <li>
+  </div>
 
-    <p>If the <span>method context</span> is a <code>Window</code> object, let <var title="">global
-    object</var> be the <span>method context</span>, let <var title="">browsing context</var> be the
-    <span>browsing context</span> with which <var title="">global object</var> is associated, let
-    <var title="">document</var> and <var title="">referrer source</var> be the
-    <code>Document</code> associated with <var title="">global object</var>, let <var
-    title="">character encoding</var> be the <span title="document's character encoding">character
-    encoding</span> of the <code>Document</code> associated with <var title="">global object</var>
-    (<a href="#sce-not-copy">this is a reference, not a copy</a>), and let <var title="">base
-    URL</var> be the <span title="document base URL">base URL</span> of the <code>Document</code>
-    associated with <var title="">global object</var> (<a href="#sbu-not-copy">this is a reference,
-    not a copy</a>).</p>
+  <div class="example">
 
-    <p>Otherwise, if the <span>method context</span> is a <code>WorkerGlobalScope</code> object, let
-    <var title="">global object</var>, <var title="">browsing context</var>, <var
-    title="">document</var>, <var title="">referrer source</var>, <var title="">character
-    encoding</var>, and <var title="">base URL</var> be the <span>script's global object</span>,
-    <span>script's browsing context</span>, <span>script's document</span>, <span>script's referrer
-    source</span>, <span>script's URL character encoding</span>, and <span>script's base URL</span>
-    (respectively) of the <span title="concept-script">script</span> that the <span>run a
-    worker</span> algorithm created when it created the <span>method context</span>.</p>
+   <p>To run tasks of several milliseconds back to back without any delay, while still yielding back
+   to the browser to avoid starving the user interface (and to avoid the browser killing the script
+   for hogging the CPU), simply queue the next timer before performing work:</p>
 
-    <p>Otherwise, act as described in the specification that defines that the
-    <code>WindowTimers</code> interface is implemented by some other object.</p>
+   <pre>function doExpensiveWork() {
+  var done = false;
+  // ...
+  // this part of the function takes up to five milliseconds
+  // set done to true if we're done
+  // ...
+  return done;
+}
 
-   </li>
+function rescheduleWork() {
+  var handle = setTimeout(rescheduleWork, 0); // preschedule next iteration
+  if (doExpensiveWork())
+    clearTimeout(handle); // clear the timeout if we don't need it
+}
 
-   <li><p>Return a <span title="concept-task">task</span> that checks if the entry for <var
-   title="">handle</var> in <var title="">list</var> has been cleared, and if it has not, <span
-   title="create a script">creates a script</span> using <var title="">script source</var> as the
-   script source, the <span>URL</span> where <var title="">script source</var> can be found, <var
-   title="">scripting language</var> as the scripting language, <var title="">global object</var> as
-   the global object, <var title="">browsing context</var> as the browsing context, <var
-   title="">document</var> as the document, <var title="">referrer source</var> as the referrer
-   source, <var title="">character encoding</var> as the URL character encoding, and <var
-   title="">base URL</var> as the base URL.</p></li>
+function scheduleWork() {
+  setTimeout(rescheduleWork, 0);
+}
 
-  </ol>
+scheduleWork(); // queues a task to do lots of work</pre>
 
-  <hr>
-
-  <p>The <span>task source</span> for these <span title="concept-task">tasks</span> is the
-  <dfn>timer task source</dfn>.</p>
-
   </div>
 
 
-
   <h3>User prompts</h3>
 
   <!--




More information about the Commit-Watchers mailing list