From 5ea60a51fe8124730e49beff5be89b4df8263a17 Mon Sep 17 00:00:00 2001 From: Domenic Denicola Date: Fri, 2 Oct 2015 15:58:22 -0400 Subject: [PATCH] Add promise rejection tracking events This new feature uses a pair of events on global scopes, viz. unhandledrejection and rejectionhandled, to allow authors to track unhandled promise rejections. The specification was originally drafted at https://github.com/domenic/unhandled-rejections-browser-spec in collaboration with @jeisinger and @bzbarsky. This feature depends on https://github.com/tc39/ecma262/pull/76. --- source | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 201 insertions(+), 3 deletions(-) diff --git a/source b/source index 23d0049d49b..5e73ff1cf1f 100644 --- a/source +++ b/source @@ -13578,7 +13578,9 @@ own thing rather than part of the extended sentence -->
onpagehide
onpageshow
onpopstate
+
onrejectionhandled
onstorage
+
onunhandledrejection
onunload
DOM interface:
@@ -85710,6 +85712,12 @@ interface NavigatorOnLine { +

An environment settings object also has an outstanding rejected promises weak set and + an about-to-be-notified rejected promises list, used in promise rejection + tracking. The outstanding rejected promises weak set 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.

+

The relevant settings object for a global object o is the environment settings object whose global object is o. (There is always a 1:1 mapping of global objects to environment settings objects.)

@@ -86196,6 +86204,159 @@ dictionary ErrorEventInit : EventInit { Where appropriate, it is set to the object representing the error (e.g. the exception object in the case of an uncaught DOM exception).

+
Unhandled promise rejections
+ +

In addition to synchronous runtime script errors, scripts + may experience asynchronous promise rejections, tracked via the unhandledrejection and rejectionhandled events.

+ + +

When the user agent is required to notify about rejected promises on a given + environment settings object settings object, it must run these steps:

+ +
    + +
  1. Let list be a copy of settings object's about-to-be-notified + rejected promises list.

  2. + +
  3. If list is empty, abort these steps.

  4. + +
  5. Clear settings object's about-to-be-notified rejected promises + list.

  6. + +
  7. + +

    Queue a task to run the following substeps for each promise p in + list:

    + +
      + +
    1. If p's [[PromiseIsHandled]] internal slot is true, continue to the next + iteration of the loop.

    2. + +
    3. Let event be a new trusted + PromiseRejectionEvent object that does not bubble but is cancelable, and which + has the event name unhandledrejection.

    4. + +
    5. Initialise event's promise attribute to p.

    6. + +
    7. Initialise event's reason attribute to the value of + p's [[PromiseResult]] internal slot.

    8. + +
    9. Dispatch event at settings object's global + object.

    10. + +
    11. If the event was canceled, then the promise rejection is handled. Otherwise, the promise rejection is + not handled.

    12. + +
    13. If p's [[PromiseIsHandled]] internal slot is false, add p to + settings object's outstanding rejected promises weak set. + +

    +
  8. + +
+ +

This algorithm results in promise rejections being marked as handled or not handled. These concepts parallel + handled and not handled script errors.

+ +

Implementations should use the handled/not handled state of promise rejections + when determining what to display in any debugging interfaces. That is, intercepting an + unhandledrejection event and calling preventDefault() should prevent + the corresponding rejection from showing up in any developer tools.

+ + +
The HostPromiseRejectionTracker implementation
+ +

ECMAScript contains an implementation-defined HostPromiseRejectionTracker(promise, + realm, operation) abstract operation. User agents must + use the following implementation:

+ +
    + +
  1. Let settings object be the environment settings object of the + global object specified by realm's [[globalThis]] internal + slot.

  2. + +
  3. +

    If operation is "reject", + +

      +
    1. Add promise to settings object's about-to-be-notified + rejected promises list.

    2. +
    +
  4. + +
  5. +

    If operation is "handle", + +

      + +
    1. If settings object's about-to-be-notified rejected promises + list contains promise, remove promise from that list and abort + these steps.

    2. + +
    3. If settings object's outstanding rejected promises weak set + does not contain promise, abort these steps.

    4. + +
    5. Remove promise from settings object's outstanding rejected + promises weak set.

    6. + +
    7. +

      Queue a task to run the following steps:

      + +
        + +
      1. Let event be a new trusted + PromiseRejectionEvent object that does not bubble and is not cancelable, and + which has the event name rejectionhandled.

      2. + +
      3. Initialise event's promise attribute to + promise.

      4. + +
      5. Initialise event's reason attribute to the value of + promise's [[PromiseResult]] internal slot.

      6. + +
      7. Dispatch event at the global object specified by + realm's [[globalThis]] internal slot.

      8. + +
      +
    8. +
    +
  6. +
+ +
The PromiseRejectionEvent interface
+ +
[Constructor(DOMString type, optional PromiseRejectionEventInit eventInitDict), Exposed=(Window,Worker)]
+interface PromiseRejectionEvent : Event {
+  readonly attribute Promise<any>? promise;
+  readonly attribute any reason;
+};
+
+dictionary PromiseRejectionEventInit : EventInit {
+  required Promise<any>? promise;
+  any reason = null;
+};
+ +

The promise attribute must + return the value it was initialised to. It represents the promise which this notification is about.

+ +

The reason attribute must + return the value it was initialised to. It represents the rejection reason for the promise.

+
@@ -86535,8 +86696,11 @@ dictionary ErrorEventInit : EventInit {
  • Remove the microtask run in the step above from the microtask queue, and return to the microtask queue handling step.

  • -
  • Done: Let the performing a microtask checkpoint flag be - false.

  • +
  • Done: For each environment settings object whose responsible + event loop is this event loop, notify about rejected promises + on that environment settings object.

  • + +
  • Let the performing a microtask checkpoint flag be false.

  • @@ -87352,7 +87516,9 @@ typedef OnBeforeUnloadEventHandlerNonNull? OnBeforeUnloadEvent onpagehide pagehide onpageshow pageshow onpopstate popstate + onrejectionhandled rejectionhandled onstorage storage + onunhandledrejection unhandledrejection onunload unload @@ -87460,7 +87626,9 @@ interface WindowEventHandlers { attribute EventHandler onpagehide; attribute EventHandler onpageshow; attribute EventHandler onpopstate; + attribute EventHandler onrejectionhandled; attribute EventHandler onstorage; + attribute EventHandler onunhandledrejection; attribute EventHandler onunload; }; @@ -94737,6 +94905,8 @@ interface WorkerGlobalScope : EventTarget { attribute EventHandler onlanguagechange; attribute EventHandler onoffline; attribute EventHandler ononline; + attribute EventHandler onrejectionhandled; + attribute EventHandler onunhandledrejection; };

    A WorkerGlobalScope object has an associated WorkerGlobalScope : EventTarget { onlanguagechange languagechange onoffline offline ononline online + onrejectionhandled rejectionhandled + onunhandledrejection unhandledrejection


    @@ -112813,7 +112985,9 @@ if (s = prompt('What is your name?')) { onpagehide; onpageshow; onpopstate; + onrejectionhandled; onstorage; + onunhandledrejection; onunload HTMLBodyElement @@ -116053,6 +116227,12 @@ if (s = prompt('What is your name?')) { resize event handler Event handler content attribute + + onrejectionhandled + body + rejectionhandled event handler for Window object + Event handler content attribute + onscroll HTML elements @@ -116125,6 +116305,12 @@ if (s = prompt('What is your name?')) { toggle event handler Event handler content attribute + + onunhandledrejection + body + unhandledrejection event handler for Window object + Event handler content attribute + onunload body @@ -116863,6 +117049,12 @@ INSERT INTERFACES HERE Document Fired at the Document when it finishes parsing and again when all its subresources have finished loading + + rejectionhandled + PromiseRejectionEvent + Global scope objects + Fired at global scope objects when a previously-unhandled promise rejection becomes handled + reset Event @@ -116905,6 +117097,12 @@ INSERT INTERFACES HERE details element Fired at details elements when they open or close + + unhandledrejection + PromiseRejectionEvent + Global scope objects + Fired at global scope objects when a promise rejection goes unhandled + unload Event @@ -117221,7 +117419,7 @@ INSERT INTERFACES HERE
    Recommendation E.163 — Numbering Plan for The International Telephone Service, CCITT Blue Book, Fascicle II.2, pp. 128-134, November 1988.
    [ECMA262]
    -
    ECMAScript Language Specification. ECMA.
    +
    ECMAScript Language Specification. Ecma.
    [ECMA357]
    (Non-normative) ECMAScript for XML (E4X) Specification. ECMA.