Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add promise rejection tracking events #224

Merged
merged 1 commit into from
Nov 30, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
219 changes: 214 additions & 5 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -13507,7 +13507,9 @@ own thing rather than part of the extended sentence -->
<dd><code data-x="handler-window-onpagehide">onpagehide</code></dd>
<dd><code data-x="handler-window-onpageshow">onpageshow</code></dd>
<dd><code data-x="handler-window-onpopstate">onpopstate</code></dd>
<dd><code data-x="handler-window-onrejectionhandled">onrejectionhandled</code></dd>
<dd><code data-x="handler-window-onstorage">onstorage</code></dd>
<dd><code data-x="handler-window-onunhandledrejection">onunhandledrejection</code></dd>
<dd><code data-x="handler-window-onunload">onunload</code></dd>
<dt><span data-x="concept-element-dom">DOM interface</span>:</dt><!--TOPIC:DOM APIs-->
<dd>
Expand Down Expand Up @@ -85879,6 +85881,13 @@ interface <dfn>NavigatorOnLine</dfn> {

</dl>

<p>An <span>environment settings object</span> also has an <dfn>outstanding rejected promises
weak set</dfn> and an <dfn>about-to-be-notified rejected promises list</dfn>, used to track
<a href="#unhandled-promise-rejections">unhandled promise rejections</a>. The <span>outstanding
rejected promises weak set</span> must not create strong references to any of its members, and
implementations are free to limit its size, e.g. by removing old entries from it when new ones
are added.</p>

<p>The <dfn>relevant settings object for a global object</dfn> <var>o</var> is the
<span>environment settings object</span> whose <span>global object</span> is <var>o</var>.
(There is always a 1:1 mapping of global objects to environment settings objects.)</p>
Expand Down Expand Up @@ -86177,7 +86186,7 @@ interface <dfn>NavigatorOnLine</dfn> {
problematic position (line number and column number), using the <span>global object</span>
specified by the <span>environment settings object</span> as the target. If the error is still <i
data-x="concept-error-nothandled">not handled</i> after this, then the error may be reported to
the user.</p>
a developer console.</p>

</li>

Expand Down Expand Up @@ -86365,6 +86374,169 @@ dictionary <dfn>ErrorEventInit</dfn> : <span>EventInit</span> {
Where appropriate, it is set to the object representing the error (e.g. the exception object in
the case of an uncaught DOM exception).</p>

<h5>Unhandled promise rejections</h5>

<p>In addition to synchronous <a href="#runtime-script-errors">runtime script errors</a>, scripts
may experience asynchronous promise rejections, tracked via the <code
data-x="event-unhandledrejection">unhandledrejection</code> and <code
data-x="event-rejectionhandled">rejectionhandled</code> events.</p>

<p>When the user agent is to <dfn>notify about rejected promises</dfn> on a given
<span>environment settings object</span> <var>settings object</var>, it must run these steps:</p>

<ol>

<li><p>Let <var>list</var> be a copy of <var>settings object</var>'s <span>about-to-be-notified
rejected promises list</span>.</p></li>

<li><p>If <var>list</var> is empty, abort these steps.</p></li>

<li><p>Clear <var>settings object</var>'s <span>about-to-be-notified rejected promises
list</span>.</p></li>

<li>

<p><span>Queue a task</span> to run the following substep:</p>

<ol>

<li><p>For each promise <var>p</var> in <var>list</var>:</p>

<ol>

<li><p>If <var>p</var>'s [[PromiseIsHandled]] internal slot is true, continue to the next
iteration of the loop.</p></li>

<li><p>Let <var>event</var> be a new <span data-x="concept-events-trusted">trusted</span>
<code>PromiseRejectionEvent</code> object that does not bubble but is cancelable, and which
has the event name <code data-x="event-unhandledrejection">unhandledrejection</code>.</p></li>

<li><p>Initialise <var>event</var>'s <code
data-x="dom-PromiseRejectionEvent-promise">promise</code> attribute to <var>p</var>.</p></li>

<li><p>Initialise <var>event</var>'s <code
data-x="dom-PromiseRejectionEvent-reason">reason</code> attribute to the value of
<var>p</var>'s [[PromiseResult]] internal slot.</p></li>

<li><p><span>Dispatch</span> <var>event</var> at <var>settings object</var>'s <span>global
object</span>.</p></li>

<li><p>If the event was canceled, then the promise rejection is <i
data-x="concept-promise-rejection-handled">handled</i>. Otherwise, the promise rejection is
<i data-x="concept-promise-rejection-nothandled">not handled</i>.</p></li>

<li><p>If <var>p</var>'s [[PromiseIsHandled]] internal slot is false, add <var>p</var> to
<var>settings object</var>'s <span>outstanding rejected promises weak set</span>.

</ol>
</li>
</ol>
</li>

</ol>

<p>This algorithm results in promise rejections being marked as <dfn
data-x="concept-promise-rejection-handled"><i>handled</i></dfn> or <dfn
data-x="concept-promise-rejection-nothandled"><i>not handled</i></dfn>. These concepts parallel
<i data-x="concept-error-handled">handled</i> and <i data-x="concept-error-nothandled">not
handled</i> script errors. If a rejection is still <i
data-x="concept-promise-rejection-nothandled">not handled</i> after this, then the rejection may
be reported to a developer console.</p>


<h6>The HostPromiseRejectionTracker implementation</h6>

<p>ECMAScript contains an implementation-defined HostPromiseRejectionTracker(<var>promise</var>,
<var>operation</var>) abstract operation. User agents must use the following implementation:
<ref spec=ECMA262></p>

<ol>

<li>
<p>Let <var>script</var> be the <span data-x="concept-script">script</span> corresponding
to the running execution context.</p>

<div class="note">The exact mechanism for correlating ECMAScript's notion of execution contexts
and HTML's notion of <span data-x="concept-script">scripts</span> is not yet well-defined. See
<a href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=25981">Bugzilla bug 25981</a> for
tentative ideas.</div>
</li>

<li><p>If <var>script</var> has <span>muted errors</span>, terminate these steps.</p></li>

<li><p>Let <var>settings object</var> be <var>script</var>'s <span>settings object</span>.</p>
</li>

<li>
<p>If <var>operation</var> is <code data-x="">"reject"</code>,

<ol>
<li><p>Add <var>promise</var> to <var>settings object</var>'s <span>about-to-be-notified
rejected promises list</span>.</p></li>
</ol>
</li>

<li>
<p>If <var>operation</var> is <code data-x="">"handle"</code>,

<ol>

<li><p>If <var>settings object</var>'s <span>about-to-be-notified rejected promises
list</span> contains <var>promise</var>, remove <var>promise</var> from that list and abort
these steps.</p></li>

<li><p>If <var>settings object</var>'s <span>outstanding rejected promises weak set</span>
does not contain <var>promise</var>, abort these steps.</p></li>

<li><p>Remove <var>promise</var> from <var>settings object</var>'s <span>outstanding rejected
promises weak set</span>.</p></li>

<li>
<p><span>Queue a task</span> to run the following steps:</p>

<ol>

<li><p>Let <var>event</var> be a new <span data-x="concept-events-trusted">trusted</span>
<code>PromiseRejectionEvent</code> object that does not bubble and is not cancelable, and
which has the event name <code
data-x="event-rejectionhandled">rejectionhandled</code>.</p></li>

<li><p>Initialise <var>event</var>'s <code
data-x="dom-PromiseRejectionEvent-promise">promise</code> attribute to
<var>promise</var>.</p></li>

<li><p>Initialise <var>event</var>'s <code
data-x="dom-PromiseRejectionEvent-reason">reason</code> attribute to the value of
<var>promise</var>'s [[PromiseResult]] internal slot.</p></li>

<li><p><span>Dispatch</span> <var>event</var> at <var>settings object</var>'s <span>global
object</span>.</p></li>

</ol>
</li>
</ol>
</li>
</ol>

<h6>The <code>PromiseRejectionEvent</code> interface</h6>

<pre class="idl">[Constructor(DOMString type, <span>PromiseRejectionEventInit</span> eventInitDict), Exposed=(Window,Worker)]
interface <dfn>PromiseRejectionEvent</dfn> : <span>Event</span> {
readonly attribute Promise&lt;any&gt; <span data-x="dom-PromiseRejectionEvent-promise">promise</span>;
readonly attribute any <span data-x="dom-PromiseRejectionEvent-reason">reason</span>;
};

dictionary <dfn>PromiseRejectionEventInit</dfn> : <span>EventInit</span> {
required Promise&lt;any&gt; promise;
any reason;
};</pre>

<p>The <dfn><code data-x="dom-PromiseRejectionEvent-promise">promise</code></dfn> attribute must
return the value it was initialised to. It represents the promise which this notification is about.</p>

<p>The <dfn><code data-x="dom-PromiseRejectionEvent-reason">reason</code></dfn> attribute must
return the value it was initialised to. It represents the rejection reason for the promise.</p>



<div w-nodev>
Expand Down Expand Up @@ -86704,8 +86876,11 @@ dictionary <dfn>ErrorEventInit</dfn> : <span>EventInit</span> {
<li><p>Remove the <span>microtask</span> run in the step above from the <span>microtask
queue</span>, and return to the <i>microtask queue handling</i> step.</p></li>

<li><p><i>Done</i>: Let the <span>performing a microtask checkpoint</span> flag be
false.</p></li>
<li><p><i>Done</i>: For each <span>environment settings object</span> whose <span>responsible
event loop</span> is this <span>event loop</span>, <span>notify about rejected promises</span>
on that <span>environment settings object</span>.</p></li>

<li><p>Let the <span>performing a microtask checkpoint</span> flag be false.</p></li>

</ol>

Expand Down Expand Up @@ -87521,7 +87696,9 @@ typedef <span>OnBeforeUnloadEventHandlerNonNull</span>? <dfn>OnBeforeUnloadEvent
<tr><td><dfn><code data-x="handler-window-onpagehide">onpagehide</code></dfn> <td> <code data-x="event-pagehide">pagehide</code> <!-- new -->
<tr><td><dfn><code data-x="handler-window-onpageshow">onpageshow</code></dfn> <td> <code data-x="event-pageshow">pageshow</code> <!-- new -->
<tr><td><dfn><code data-x="handler-window-onpopstate">onpopstate</code></dfn> <td> <code data-x="event-popstate">popstate</code> <!-- new -->
<tr><td><dfn><code data-x="handler-window-onrejectionhandled">onrejectionhandled</code></dfn> <td> <code data-x="event-rejectionhandled">rejectionhandled</code>
<tr><td><dfn><code data-x="handler-window-onstorage">onstorage</code></dfn> <td> <code data-x="event-storage">storage</code> <!-- new -->
<tr><td><dfn><code data-x="handler-window-onunhandledrejection">onunhandledrejection</code></dfn> <td> <code data-x="event-unhandledrejection">unhandledrejection</code>
<tr><td><dfn><code data-x="handler-window-onunload">onunload</code></dfn> <td> <code data-x="event-unload">unload</code> <!-- widely used -->
</table>

Expand Down Expand Up @@ -87629,7 +87806,9 @@ interface <dfn>WindowEventHandlers</dfn> {
attribute <span>EventHandler</span> <span data-x="handler-window-onpagehide">onpagehide</span>;
attribute <span>EventHandler</span> <span data-x="handler-window-onpageshow">onpageshow</span>;
attribute <span>EventHandler</span> <span data-x="handler-window-onpopstate">onpopstate</span>;
attribute <span>EventHandler</span> <span data-x="handler-window-onrejectionhandled">onrejectionhandled</span>;
attribute <span>EventHandler</span> <span data-x="handler-window-onstorage">onstorage</span>;
attribute <span>EventHandler</span> <span data-x="handler-window-onunhandledrejection">onunhandledrejection</span>;
attribute <span>EventHandler</span> <span data-x="handler-window-onunload">onunload</span>;
};</pre>

Expand Down Expand Up @@ -94909,6 +95088,8 @@ interface <dfn>WorkerGlobalScope</dfn> : <span>EventTarget</span> {
attribute <span>EventHandler</span> <span data-x="handler-WorkerGlobalScope-onlanguagechange">onlanguagechange</span>;
attribute <span>EventHandler</span> <span data-x="handler-WorkerGlobalScope-onoffline">onoffline</span>;
attribute <span>EventHandler</span> <span data-x="handler-WorkerGlobalScope-ononline">ononline</span>;
attribute <span>EventHandler</span> <span data-x="handler-WorkerGlobalScope-onrejectionhandled">onrejectionhandled</span>;
attribute <span>EventHandler</span> <span data-x="handler-WorkerGlobalScope-onunhandledrejection">onunhandledrejection</span>;
};</pre>

<p>A <code>WorkerGlobalScope</code> object has an associated <dfn data-dfn-for="WorkerGlobalScope"
Expand Down Expand Up @@ -94967,6 +95148,8 @@ interface <dfn>WorkerGlobalScope</dfn> : <span>EventTarget</span> {
<tr><td><dfn><code data-x="handler-WorkerGlobalScope-onlanguagechange">onlanguagechange</code></dfn> <td> <code data-x="event-languagechange">languagechange</code> <!-- new -->
<tr><td><dfn><code data-x="handler-WorkerGlobalScope-onoffline">onoffline</code></dfn> <td> <code data-x="event-offline">offline</code> <!-- new -->
<tr><td><dfn><code data-x="handler-WorkerGlobalScope-ononline">ononline</code></dfn> <td> <code data-x="event-online">online</code> <!-- new -->
<tr><td><dfn><code data-x="handler-WorkerGlobalScope-onrejectionhandled">onrejectionhandled</code></dfn> <td> <code data-x="event-rejectionhandled">rejectionhandled</code>
<tr><td><dfn><code data-x="handler-WorkerGlobalScope-onunhandledrejection">onunhandledrejection</code></dfn> <td> <code data-x="event-unhandledrejection">unhandledrejection</code>
</table>


Expand Down Expand Up @@ -112984,7 +113167,9 @@ if (s = prompt('What is your name?')) {
<code data-x="handler-window-onpagehide">onpagehide</code>;
<code data-x="handler-window-onpageshow">onpageshow</code>;
<code data-x="handler-window-onpopstate">onpopstate</code>;
<code data-x="handler-window-onrejectionhandled">onrejectionhandled</code>;
<code data-x="handler-window-onstorage">onstorage</code>;
<code data-x="handler-window-onunhandledrejection">onunhandledrejection</code>;
<code data-x="handler-window-onunload">onunload</code></td>
<td><code>HTMLBodyElement</code></td>
</tr>
Expand Down Expand Up @@ -116216,6 +116401,12 @@ if (s = prompt('What is your name?')) {
<td> <code data-x="event-resize">resize</code> event handler
<td> <span data-x="event handler content attributes">Event handler content attribute</span>

<tr>
<th id="ix-handler-window-onrejectionhandled"> <code data-x="">onrejectionhandled</code>
<td> <code data-x="handler-window-onrejectionhandled">body</code>
<td> <code data-x="event-rejectionhandled">rejectionhandled</code> event handler for <code>Window</code> object
<td> <span data-x="event handler content attributes">Event handler content attribute</span>

<tr>
<th id="ix-handler-onscroll"> <code data-x="">onscroll</code>
<td> <span data-x="handler-onscroll">HTML elements</span>
Expand Down Expand Up @@ -116288,6 +116479,12 @@ if (s = prompt('What is your name?')) {
<td> <code data-x="event-toggle">toggle</code> event handler
<td> <span data-x="event handler content attributes">Event handler content attribute</span>

<tr>
<th id="ix-handler-window-onunhandledrejection"> <code data-x="">onunhandledrejection</code>
<td> <code data-x="handler-window-onunhandledrejection">body</code>
<td> <code data-x="event-unhandledrejection">unhandledrejection</code> event handler for <code>Window</code> object
<td> <span data-x="event handler content attributes">Event handler content attribute</span>

<tr>
<th id="ix-handler-window-onunload"> <code data-x="">onunload</code>
<td> <code data-x="handler-window-onunload">body</code>
Expand Down Expand Up @@ -117026,6 +117223,12 @@ INSERT INTERFACES HERE
<td> <code>Document</code>
<td> Fired at the <code>Document</code> when it finishes parsing and again when all its subresources have finished loading

<tr> <!-- rejectionhandled -->
<td> <dfn><code data-x="event-rejectionhandled">rejectionhandled</code></dfn>
<td> <code>PromiseRejectionEvent</code>
<td> Global scope objects
<td> Fired at global scope objects when a previously-unhandled promise rejection becomes handled

<tr> <!-- reset -->
<td> <dfn><code data-x="event-reset">reset</code></dfn>
<td> <code>Event</code>
Expand Down Expand Up @@ -117068,6 +117271,12 @@ INSERT INTERFACES HERE
<td> <code>details</code> element
<td> Fired at <code>details</code> elements when they open or close

<tr> <!-- unhandledrejection -->
<td> <dfn><code data-x="event-unhandledrejection">unhandledrejection</code></dfn>
<td> <code>PromiseRejectionEvent</code>
<td> Global scope objects
<td> Fired at global scope objects when a promise rejection goes unhandled

<tr> <!-- unload -->
<td> <dfn><code data-x="event-unload">unload</code></dfn>
<td> <code>Event</code>
Expand Down Expand Up @@ -117384,10 +117593,10 @@ INSERT INTERFACES HERE
<dd><cite>Recommendation E.163 &mdash; Numbering Plan for The International Telephone Service</cite>, CCITT Blue Book, Fascicle II.2, pp. 128-134, November 1988.</dd>

<dt id="refsECMA262">[ECMA262]</dt>
<dd><cite><a href="https://people.mozilla.org/~jorendorff/es6-draft.html">ECMAScript Language Specification</a></cite>. ECMA.</dd>
<dd><cite><a href="https://tc39.github.io/ecma262/">ECMAScript Language Specification</a></cite>. Ecma International.</dd>

<dt id="refsECMA357">[ECMA357]</dt>
<dd>(Non-normative) <cite><a href="http://www.ecma-international.org/publications/standards/Ecma-357.htm">ECMAScript for XML (E4X) Specification</a></cite>. ECMA.</dd>
<dd>(Non-normative) <cite><a href="http://www.ecma-international.org/publications/standards/Ecma-357.htm">ECMAScript for XML (E4X) Specification</a></cite>. Ecma International.</dd>

<dt id="refsEDITING">[EDITING]</dt>
<dd><cite><a href="https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html">HTML Editing APIs</a></cite>, A. Gregor. W3C Editing APIs CG.</dd>
Expand Down