Permalink
Browse files

Integrate with the ES job queue

This integrates with the ES job queue for promise jobs, by overriding ES's EnqueueJob and NextJob to delegate to the microtask queue. This finally gives us a normative specification for how promises interface with the browser event loop.

This approach of monkeypatching ES is necessary for now. See discussions in tc39/ecma262#240 (comment) about how this is the least-bad alternative. We hope to update ES to delegate to the host for those operations in the future, instead of overwriting ES. That possibility is discussed in replies to the linked comment.

Also fixes a few uses of "ECMAScript"; this specification prefers "JavaScript".

This completes https://www.w3.org/Bugs/Public/show_bug.cgi?id=25981.
  • Loading branch information...
domenic committed Dec 15, 2015
1 parent 704907d commit 12db63c7c038b9d8f1d3501d6661d89d495abeac
Showing with 66 additions and 3 deletions.
  1. +66 −3 source
View
69 source
@@ -2937,7 +2937,7 @@ a.setAttribute('href', 'http://example.com/'); // change the content attribute d
data-x="willful violation">despite it being an officially obsoleted type</span> according to RFC
4329. <ref spec=RFC4329></p>
<p>The following terms are defined in the ECMAScript specification and used in this specification:</p>
<p>The following terms are defined in the JavaScript specification and used in this specification:</p>
<ul class="brief">
@@ -2951,6 +2951,7 @@ a.setAttribute('href', 'http://example.com/'); // change the content attribute d
<li><dfn data-noexport="" data-x-href="https://tc39.github.io/ecma262/#use-strict-directive">Use Strict Directive</dfn>
<li>The <dfn data-noexport="" data-x="js-prod-Pattern" data-x-href="https://tc39.github.io/ecma262/#prod-Pattern"><i>Pattern</i></dfn> production</li>
<li>The <dfn data-noexport="" data-x="js-prod-FunctionBody" data-x-href="https://tc39.github.io/ecma262/#prod-FunctionBody"><i>FunctionBody</i></dfn> production</li>
<li>The <dfn data-noexport="" data-x="js-EnqueueJob" data-x-href="https://tc39.github.io/ecma262/#sec-enqueuejob">EnqueueJob</dfn> abstract operation</li>
<li>The <dfn data-noexport="" data-x="js-FunctionCreate" data-x-href="https://tc39.github.io/ecma262/#sec-functioncreate">FunctionCreate</dfn> abstract operation</li>
<li>The <dfn data-noexport="" data-x="js-GetActiveScriptOrModule" data-x-href="https://tc39.github.io/ecma262/#sec-getactivescriptormodule">GetActiveScriptOrModule</dfn> abstract operation</li>
<li>The <dfn data-noexport="" data-x="js-HostPromiseRejectionTracker" data-x-href="https://tc39.github.io/ecma262/#sec-host-promise-rejection-tracker">HostPromiseRejectionTracker</dfn> abstract operation</li>
@@ -2959,6 +2960,7 @@ a.setAttribute('href', 'http://example.com/'); // change the content attribute d
<li>The <dfn data-noexport="" data-x="js-ParseScript" data-x-href="https://tc39.github.io/ecma262/#sec-parse-script">ParseScript</dfn> abstract operation</li>
<li>The <dfn data-noexport="" data-x="js-ScriptEvaluation" data-x-href="https://tc39.github.io/ecma262/#sec-runtime-semantics-scriptevaluation">ScriptEvaluation</dfn> abstract operation</li>
<li>The <dfn data-noexport="" data-x="js-ToBoolean" data-x-href="https://tc39.github.io/ecma262/#sec-toboolean">ToBoolean</dfn> abstract operation</li>
<li>The <dfn data-noexport="" data-x="js-NextJob" data-x-href="https://tc39.github.io/ecma262/#sec-nextjob-result">NextJob</dfn> algorithm step
<li>The <dfn data-noexport="" data-x="js-abstract-equality" data-x-href="https://tc39.github.io/ecma262/#sec-abstract-equality-comparison">Abstract Equality Comparison</dfn> algorithm
<li>The <dfn data-noexport="" data-x="js-strict-equality" data-x-href="https://tc39.github.io/ecma262/#sec-strict-equality-comparison">Strict Equality Comparison</dfn> algorithm
<li>The <dfn data-noexport="" data-x-href="https://tc39.github.io/ecma262/#sec-date-objects"><code>Date</code></dfn> class
@@ -61788,7 +61790,7 @@ interface <dfn>Path2D</dfn> {
<li><p>Let <var>input</var> be the argument to coerce.</p></li>
<li><p>Let <var>jsval</var> be the result of <span data-x="concept-idl-convert">converting</span>
<var>input</var> to an ECMAScript value. If this throws an exception, then propagate the
<var>input</var> to a JavaScript value. If this throws an exception, then propagate the
exception and abort these steps.</p></li>
<li><p>Let <var>dict</var> be the result of <span data-x="concept-idl-convert">converting</span>
@@ -86119,6 +86121,67 @@ interface <dfn>NavigatorOnLine</dfn> {
user with a mechanism to just close the page entirely, without running any <code
data-x="event-unload">unload</code> event handlers.</p>
<h5>Integration with the JavaScript job queue</h5>
<p>The JavaScript specification defines the JavaScript job and job queue abstractions in order to
specify certain invariants about how promise operations execute with a clean <span>JavaScript
execution context stack</span> and in a certain order. However, as of the time of this writing
the definitions of <span data-x="js-EnqueueJob">EnqueueJob</span> and <span
data-x="js-NextJob">NextJob</span> in that specification are not sufficiently flexible to
integrate with HTML as a host environment. <ref spec="ECMA262"></p>
<p class="note">This is not strictly true. It is in fact possible, by taking liberal advantage of
the many "implementation defined" sections of those algorithms, to contort them to our purposes.
However, the end result is a mass of messy indirection and workarounds that essentially bypasses
the job queue infrastructure entirely, albeit in a way that is technically sanctioned within the
bounds of implementation-defined behavior. We do not take this path, and instead introduce the
following <span data-x="willful violation">willful violations</span>.</p>
<p>As such, user agents must instead use the following definitions in place of those in the
JavaScript specification. These ensure that the promise jobs enqueued by the JavaScript
specification are properly integrated into the user agent's <span data-x="event loop">event
loops</span>.</p>
<h6><dfn>EnqueueJob</dfn>(<var>queueName</var>, <var>job</var>, <var>arguments</var>)</h6>
<p>When the JavaScript specification says to call the EnqueueJob abstract operation, the
following algorithm must be used in place of JavaScript's <span
data-x="js-EnqueueJob">EnqueueJob</span>:</p>
<ol>
<li><p>Assert: <var>queueName</var> is <code data-x="">"PromiseJobs"</code>. (<code
data-x="">"ScriptJobs"</code> must not be used by user agents.)</p></li>
<li><p>Let <var>settings</var> be the <span>settings object</span> of <span>the script
corresponding to the running execution context</span>.</p></li>
<li>
<p><span>Queue a microtask</span>, on <var>settings</var>'s <span>responsible event
loop</span>, to perform the following steps:</p>
<ol>
<li><p><span>Prepare to run a callback</span> with <var>settings</var>. If this returns "do
not run" then abort these steps.</p></li>
<li><p>Performing the abstract operation specified by <var>job</var>, using the elements of
<var>arguments</var> as its arguments.</p></li>
<li><p><span>Clean up after running a callback</span> with <var>settings</var>.</p></li>
</ol>
</li>
</ol>
<h6><dfn>NextJob</dfn> <var>result</var></h6>
<p>When the JavaScript specification uses the algorithm step NextJob, the following steps must be
used in place of those specified by JavaScript's <span data-x="js-NextJob">NextJob</span>:</p>
<ol>
<li><p>If <var>result</var> is an abrupt completion, <span>report the exception</span> given by
<var>result</var>.[[value]].</p></li>
</ol>
<p class="note">A more accurate name for our overridden version of NextJob would be along the
lines of "yield to host environment" or "allow host environment to react to job results". The
process of actually initiating the next job will be taken care of by the <span>event
loop</span>.</p>
</div>
@@ -86332,7 +86395,7 @@ dictionary <dfn>ErrorEventInit</dfn> : <span>EventInit</span> {
<h6>The HostPromiseRejectionTracker implementation</h6>
<p>ECMAScript contains an implementation-defined <span
<p>JavaScript contains an implementation-defined <span
data-x="js-HostPromiseRejectionTracker">HostPromiseRejectionTracker</span>(<var>promise</var>,
<var>operation</var>) abstract operation. User agents must use the following implementation:
<ref spec=ECMA262></p>

0 comments on commit 12db63c

Please sign in to comment.