Skip to content

Commit

Permalink
Integrate with the ES job queue
Browse files Browse the repository at this point in the history
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 dd665d7 commit e4dc76e
Showing 1 changed file with 64 additions and 3 deletions.
67 changes: 64 additions & 3 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -2938,7 +2938,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">

Expand All @@ -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>
Expand All @@ -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
Expand Down Expand Up @@ -61668,7 +61670,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>
Expand Down Expand Up @@ -85954,6 +85956,65 @@ 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-NextJob">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".</p>

</div>


Expand Down Expand Up @@ -86167,7 +86228,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>
Expand Down

0 comments on commit e4dc76e

Please sign in to comment.