Re: [whatwg] An API for unhandled promise rejections
Yes, see: - https://lists.w3.org/Archives/Public/public-whatwg-archive/2015May/0051.html - https://github.com/domenic/unhandled-rejections-browser-spec - https://codereview.chromium.org/1179113007/ > -Original Message- > From: Conrad Irwin [mailto:conrad.ir...@gmail.com] > Sent: Wednesday, June 17, 2015 14:40 > To: wha...@whatwg.org; Domenic Denicola > Subject: Re: [whatwg] An API for unhandled promise rejections > > Hi Domenic, > > Sorry to re-open an old thread; but this is important to me :). > > Do you know if there’s been any progress on getting this behavior > standardized (or even better, implemented)? > > Conrad
Re: [whatwg] An API for unhandled promise rejections
On Tue, May 19, 2015 at 2:07 PM, Domenic Denicola wrote: >> An API being proposed on a mailing list such as this one? > > The API is already proposed (see the rest of this thread). Ah, sorry, I misunderstood your earlier email to mean that you were intending to experiment with the API as well. / Jonas
Re: [whatwg] An API for unhandled promise rejections
From: Jonas Sicking [mailto:jo...@sicking.cc] > An API being proposed on a mailing list such as this one? The API is already proposed (see the rest of this thread). The exact timing is tricky to figure out without a working implementation to play with, compare to real-world code, tweak, adjust, write and run test cases against. I could conjecture a timing without that information, but I'd prefer to gather it first before stating anything even halfway definitive.
Re: [whatwg] An API for unhandled promise rejections
On Tue, May 19, 2015 at 2:04 PM, Domenic Denicola wrote: > From: whatwg [mailto:whatwg-boun...@lists.whatwg.org] On Behalf Of Jonas > Sicking > >> That sounds hard to provide feedback on... > > What working mode would you prefer? An API being proposed on a mailing list such as this one? / Jonas
Re: [whatwg] An API for unhandled promise rejections
On Tue, May 19, 2015 at 2:02 PM, Jonas Sicking wrote: > On Tue, May 19, 2015 at 1:57 PM, Domenic Denicola wrote: > >> It's hard to say what "this" you're talking about implementing in > Chrome in > >> terms of the task-queueing behavior. Is that something you just haven't > >> decided on yet? > > > > Yeah, I think this will be something that gets nailed down more during > implementation and writing of test cases. > > That sounds hard to provide feedback on... > > Note that of the options mentioned above, there's no way to have "a task after all tasks" or a "a microtask after all microtasks" because both are loops so there's no concept of "after all". At best it seems either this posts a task or a microtask. - E
Re: [whatwg] An API for unhandled promise rejections
From: whatwg [mailto:whatwg-boun...@lists.whatwg.org] On Behalf Of Jonas Sicking > That sounds hard to provide feedback on... What working mode would you prefer?
Re: [whatwg] An API for unhandled promise rejections
On Tue, May 19, 2015 at 1:57 PM, Domenic Denicola wrote: >> It's hard to say what "this" you're talking about implementing in Chrome in >> terms of the task-queueing behavior. Is that something you just haven't >> decided on yet? > > Yeah, I think this will be something that gets nailed down more during > implementation and writing of test cases. That sounds hard to provide feedback on... / Jonas
Re: [whatwg] An API for unhandled promise rejections
From: Boris Zbarsky [mailto:bzbar...@mit.edu] > We (Mozilla) support having something here. Great! Thanks for your reply. And sorry for the lack of the specifics. We'll work on nailing something down (spec-wise) as we implement, and of course far ahead of any shipping. I'll reply when I get a repo up. > Not making the error event > even more complicated than it already is makes sense. That's good feedback given the internal split of opinions. Hopefully enough to tip the balance. > Presumably > whatever the new events are would also get propagated from worker global > scope to worker? Agreed. > Event names in the web platform are typically lowercase, not camelCase. For sure. > It's hard to say what "this" you're talking about implementing in Chrome in > terms of the task-queueing behavior. Is that something you just haven't > decided on yet? Yeah, I think this will be something that gets nailed down more during implementation and writing of test cases.
Re: [whatwg] An API for unhandled promise rejections
On 5/18/15 6:49 PM, Domenic Denicola wrote: Ping. We're considering implementing this in Chrome and it would be helpful to get a sense if other vendors support this. We (Mozilla) support having something here. Not making the error event even more complicated than it already is makes sense. Presumably whatever the new events are would also get propagated from worker global scope to worker? Event names in the web platform are typically lowercase, not camelCase. It's hard to say what "this" you're talking about implementing in Chrome in terms of the task-queueing behavior. Is that something you just haven't decided on yet? Past that, I'm not sure we have any particular thoughts on the details here so far... -Boris
Re: [whatwg] An API for unhandled promise rejections
The OP proposal. > -Original Message- > From: whatwg [mailto:whatwg-boun...@lists.whatwg.org] On Behalf Of > Elliott Sprehn > Sent: Monday, May 18, 2015 19:23 > To: Domenic Denicola > Cc: WHATWG; Boris Zbarsky; Brian Terlson > Subject: Re: [whatwg] An API for unhandled promise rejections > > What of the many things in that email are you considering? > > On Mon, May 18, 2015 at 3:49 PM, Domenic Denicola > wrote: > > > Ping. We're considering implementing this in Chrome and it would be > > helpful to get a sense if other vendors support this. > > > > > -Original Message- > > > From: whatwg [mailto:whatwg-boun...@lists.whatwg.org] On Behalf Of > > > Domenic Denicola > > > Sent: Monday, February 9, 2015 20:45 > > > To: WHATWG > > > Cc: Petka Antonov > > > Subject: Re: [whatwg] An API for unhandled promise rejections > > > > > > An update on this: although the conversation somewhat fizzled here, > > > in > > io.js > > > (Node.js fork) something very similar is landing and I'm trying to > > > guide > > it > > > toward being reasonably compatible with browsers [1]. Additionally > > several > > > promise libraries have implemented similar hooks (see [2] and links > > > in > > the > > > comments; also of interest is the analysis of how promise-using > > libraries use > > > these hooks). > > > > > > The community largely settled on > > > unhandledRejection/rejectionHandled, > > > instead of hijacking the error event like the original post below > > proposes. > > > Which is not to say that we have to respect that in browsers, but > > > it's a > > data > > > point to consider. > > > > > > One interesting question that came up is the exact timing of the > > > unhandledRejection event. In my proto-spec at [3] I proposed queuing > > > a separate notify-rejected task for each rejection, largely because > > > it > > seemed > > > the easiest thing to spec. We now have some experience from the field. > > The > > > implementation at [1] considered a few approaches and cycled through > > > implementing some subset of them to make a progressively-larger set > > > of tests pass: > > > > > > - Queue a single task > > > - Queue a separate task per rejection (as in proto-spec) > > > - Queue a microtask that occurs after all other microtasks > > > - Queue a task that occurs after all other tasks > > > > > > Hopefully Petka, CC'ed, can correct me if I misstated these and fill > > > in > > any > > > details I missed. > > > > > > In general I am in favor of pushing off notification as long as > > > possible > > to give > > > more time for the rejection to potentially become handled (and thus > > > decrease false positives). From this perspective either separate > > > task per rejection or after-all-others task seems good. I was hoping > > > to get a web platform perspective on what sounds good and would be > implementable? > > > For example I think the after-all-others-task can be specced with a > > > new > > task > > > source that HTML mandates is drained after all others, right? > > > > > > Anyway, I mostly just wanted to give people an update and show that > > > we're prototyping this in io.js. Hopefully the interchange of ideas > > > here can > > help > > > push the progress in browsers too. > > > > > > > > > [1]: https://github.com/iojs/io.js/pull/758 > > > [2]: https://gist.github.com/benjamingr/0237932cee84712951a2 > > > [3]: > > > https://gist.github.com/domenic/9b40029f59f29b822f3b#promise-error- > > > handling-hooks-rough-spec-algorithm > > > > > > > > > -Original Message- > > > From: Domenic Denicola > > > Sent: Friday, September 12, 2014 14:34 > > > To: WHATWG > > > Subject: An API for unhandled promise rejections > > > > > > ## Problem > > > > > > A common desire in web programming is to log any uncaught exceptions > > > back to the server. The typical method for doing this is > > > > > > window.onerror = (message, url, line, column, error) => { > > > // log `error` back to the server > > > }; > > > > > > When programming asynchronously with promises, asynchronous > > > exce
Re: [whatwg] An API for unhandled promise rejections
What of the many things in that email are you considering? On Mon, May 18, 2015 at 3:49 PM, Domenic Denicola wrote: > Ping. We're considering implementing this in Chrome and it would be > helpful to get a sense if other vendors support this. > > > -Original Message- > > From: whatwg [mailto:whatwg-boun...@lists.whatwg.org] On Behalf Of > > Domenic Denicola > > Sent: Monday, February 9, 2015 20:45 > > To: WHATWG > > Cc: Petka Antonov > > Subject: Re: [whatwg] An API for unhandled promise rejections > > > > An update on this: although the conversation somewhat fizzled here, in > io.js > > (Node.js fork) something very similar is landing and I'm trying to guide > it > > toward being reasonably compatible with browsers [1]. Additionally > several > > promise libraries have implemented similar hooks (see [2] and links in > the > > comments; also of interest is the analysis of how promise-using > libraries use > > these hooks). > > > > The community largely settled on unhandledRejection/rejectionHandled, > > instead of hijacking the error event like the original post below > proposes. > > Which is not to say that we have to respect that in browsers, but it's a > data > > point to consider. > > > > One interesting question that came up is the exact timing of the > > unhandledRejection event. In my proto-spec at [3] I proposed queuing a > > separate notify-rejected task for each rejection, largely because it > seemed > > the easiest thing to spec. We now have some experience from the field. > The > > implementation at [1] considered a few approaches and cycled through > > implementing some subset of them to make a progressively-larger set of > > tests pass: > > > > - Queue a single task > > - Queue a separate task per rejection (as in proto-spec) > > - Queue a microtask that occurs after all other microtasks > > - Queue a task that occurs after all other tasks > > > > Hopefully Petka, CC'ed, can correct me if I misstated these and fill in > any > > details I missed. > > > > In general I am in favor of pushing off notification as long as possible > to give > > more time for the rejection to potentially become handled (and thus > > decrease false positives). From this perspective either separate task per > > rejection or after-all-others task seems good. I was hoping to get a web > > platform perspective on what sounds good and would be implementable? > > For example I think the after-all-others-task can be specced with a new > task > > source that HTML mandates is drained after all others, right? > > > > Anyway, I mostly just wanted to give people an update and show that we're > > prototyping this in io.js. Hopefully the interchange of ideas here can > help > > push the progress in browsers too. > > > > > > [1]: https://github.com/iojs/io.js/pull/758 > > [2]: https://gist.github.com/benjamingr/0237932cee84712951a2 > > [3]: https://gist.github.com/domenic/9b40029f59f29b822f3b#promise-error- > > handling-hooks-rough-spec-algorithm > > > > > > -Original Message- > > From: Domenic Denicola > > Sent: Friday, September 12, 2014 14:34 > > To: WHATWG > > Subject: An API for unhandled promise rejections > > > > ## Problem > > > > A common desire in web programming is to log any uncaught exceptions > > back to the server. The typical method for doing this is > > > > window.onerror = (message, url, line, column, error) => { > > // log `error` back to the server > > }; > > > > When programming asynchronously with promises, asynchronous > > exceptions are encapsulated as _rejected promises_. They can be caught > > and handled with `promise.catch(err => ...)`, and propagate up through an > > "asynchronous call stack" (i.e. a promise chain) in a similar manner to > > synchronous errors. > > > > However, for promises, there is no notion of the "top-level" of the > promise > > chain at which the rejection is known to be unhandled. Promises are > > inherently temporal, and at any time code that has access to a given > promise > > could handle the rejection it encapsulates. Thus, unlike with synchronous > > code, there is not an ever-growing list of unhandled exceptions: instead, > > there is a growing and shrinking list of currently-unhandled rejections. > > > > For developers to be able to debug promises effectively, this live list > of > > currently-unhandled reject
Re: [whatwg] An API for unhandled promise rejections
Ping. We're considering implementing this in Chrome and it would be helpful to get a sense if other vendors support this. > -Original Message- > From: whatwg [mailto:whatwg-boun...@lists.whatwg.org] On Behalf Of > Domenic Denicola > Sent: Monday, February 9, 2015 20:45 > To: WHATWG > Cc: Petka Antonov > Subject: Re: [whatwg] An API for unhandled promise rejections > > An update on this: although the conversation somewhat fizzled here, in io.js > (Node.js fork) something very similar is landing and I'm trying to guide it > toward being reasonably compatible with browsers [1]. Additionally several > promise libraries have implemented similar hooks (see [2] and links in the > comments; also of interest is the analysis of how promise-using libraries use > these hooks). > > The community largely settled on unhandledRejection/rejectionHandled, > instead of hijacking the error event like the original post below proposes. > Which is not to say that we have to respect that in browsers, but it's a data > point to consider. > > One interesting question that came up is the exact timing of the > unhandledRejection event. In my proto-spec at [3] I proposed queuing a > separate notify-rejected task for each rejection, largely because it seemed > the easiest thing to spec. We now have some experience from the field. The > implementation at [1] considered a few approaches and cycled through > implementing some subset of them to make a progressively-larger set of > tests pass: > > - Queue a single task > - Queue a separate task per rejection (as in proto-spec) > - Queue a microtask that occurs after all other microtasks > - Queue a task that occurs after all other tasks > > Hopefully Petka, CC'ed, can correct me if I misstated these and fill in any > details I missed. > > In general I am in favor of pushing off notification as long as possible to > give > more time for the rejection to potentially become handled (and thus > decrease false positives). From this perspective either separate task per > rejection or after-all-others task seems good. I was hoping to get a web > platform perspective on what sounds good and would be implementable? > For example I think the after-all-others-task can be specced with a new task > source that HTML mandates is drained after all others, right? > > Anyway, I mostly just wanted to give people an update and show that we're > prototyping this in io.js. Hopefully the interchange of ideas here can help > push the progress in browsers too. > > > [1]: https://github.com/iojs/io.js/pull/758 > [2]: https://gist.github.com/benjamingr/0237932cee84712951a2 > [3]: https://gist.github.com/domenic/9b40029f59f29b822f3b#promise-error- > handling-hooks-rough-spec-algorithm > > > -Original Message- > From: Domenic Denicola > Sent: Friday, September 12, 2014 14:34 > To: WHATWG > Subject: An API for unhandled promise rejections > > ## Problem > > A common desire in web programming is to log any uncaught exceptions > back to the server. The typical method for doing this is > > window.onerror = (message, url, line, column, error) => { > // log `error` back to the server > }; > > When programming asynchronously with promises, asynchronous > exceptions are encapsulated as _rejected promises_. They can be caught > and handled with `promise.catch(err => ...)`, and propagate up through an > "asynchronous call stack" (i.e. a promise chain) in a similar manner to > synchronous errors. > > However, for promises, there is no notion of the "top-level" of the promise > chain at which the rejection is known to be unhandled. Promises are > inherently temporal, and at any time code that has access to a given promise > could handle the rejection it encapsulates. Thus, unlike with synchronous > code, there is not an ever-growing list of unhandled exceptions: instead, > there is a growing and shrinking list of currently-unhandled rejections. > > For developers to be able to debug promises effectively, this live list of > currently-unhandled rejections certainly needs to be exposed via developer > tools, similar to how devtools exposes the ever-growing list of unhandled > exceptions (via console output). However, developer tools are not sufficient > to satisfy the telemetry use case, i.e. the use case which is currently > handled > via `window.onerror` for synchronous code. > > ## Proposed Solution > > We propose that > > 1. `window.onerror` be extended to handle the rejected-promise use case, > notifying about any promises that, "at the end of the task queue", contain > rejections that are not yet handled; and 2. A new hoo
Re: [whatwg] An API for unhandled promise rejections
On 2/9/15 8:45 PM, Domenic Denicola wrote: - Queue a task that occurs after all other tasks On many web pages, this would effectively mean "never" because they post tasks all the time... -Boris
Re: [whatwg] An API for unhandled promise rejections
An update on this: although the conversation somewhat fizzled here, in io.js (Node.js fork) something very similar is landing and I'm trying to guide it toward being reasonably compatible with browsers [1]. Additionally several promise libraries have implemented similar hooks (see [2] and links in the comments; also of interest is the analysis of how promise-using libraries use these hooks). The community largely settled on unhandledRejection/rejectionHandled, instead of hijacking the error event like the original post below proposes. Which is not to say that we have to respect that in browsers, but it's a data point to consider. One interesting question that came up is the exact timing of the unhandledRejection event. In my proto-spec at [3] I proposed queuing a separate notify-rejected task for each rejection, largely because it seemed the easiest thing to spec. We now have some experience from the field. The implementation at [1] considered a few approaches and cycled through implementing some subset of them to make a progressively-larger set of tests pass: - Queue a single task - Queue a separate task per rejection (as in proto-spec) - Queue a microtask that occurs after all other microtasks - Queue a task that occurs after all other tasks Hopefully Petka, CC'ed, can correct me if I misstated these and fill in any details I missed. In general I am in favor of pushing off notification as long as possible to give more time for the rejection to potentially become handled (and thus decrease false positives). From this perspective either separate task per rejection or after-all-others task seems good. I was hoping to get a web platform perspective on what sounds good and would be implementable? For example I think the after-all-others-task can be specced with a new task source that HTML mandates is drained after all others, right? Anyway, I mostly just wanted to give people an update and show that we're prototyping this in io.js. Hopefully the interchange of ideas here can help push the progress in browsers too. [1]: https://github.com/iojs/io.js/pull/758 [2]: https://gist.github.com/benjamingr/0237932cee84712951a2 [3]: https://gist.github.com/domenic/9b40029f59f29b822f3b#promise-error-handling-hooks-rough-spec-algorithm -Original Message- From: Domenic Denicola Sent: Friday, September 12, 2014 14:34 To: WHATWG Subject: An API for unhandled promise rejections ## Problem A common desire in web programming is to log any uncaught exceptions back to the server. The typical method for doing this is window.onerror = (message, url, line, column, error) => { // log `error` back to the server }; When programming asynchronously with promises, asynchronous exceptions are encapsulated as _rejected promises_. They can be caught and handled with `promise.catch(err => ...)`, and propagate up through an "asynchronous call stack" (i.e. a promise chain) in a similar manner to synchronous errors. However, for promises, there is no notion of the "top-level" of the promise chain at which the rejection is known to be unhandled. Promises are inherently temporal, and at any time code that has access to a given promise could handle the rejection it encapsulates. Thus, unlike with synchronous code, there is not an ever-growing list of unhandled exceptions: instead, there is a growing and shrinking list of currently-unhandled rejections. For developers to be able to debug promises effectively, this live list of currently-unhandled rejections certainly needs to be exposed via developer tools, similar to how devtools exposes the ever-growing list of unhandled exceptions (via console output). However, developer tools are not sufficient to satisfy the telemetry use case, i.e. the use case which is currently handled via `window.onerror` for synchronous code. ## Proposed Solution We propose that 1. `window.onerror` be extended to handle the rejected-promise use case, notifying about any promises that, "at the end of the task queue", contain rejections that are not yet handled; and 2. A new hook, `window.onrejectionhandled`, be added, to notify when (or if) such rejections eventually become handled. By "at the end of the task queue" I mean that upon a promise being rejected with no handlers, we would queue a task to fire an error event; however if a handler is then attached to a promise in the meantime, a flag would be set so that when the task executes nothing actually happens. ### Developer Experience In terms of developer experience, the result is that if a promise is rejected without any rejection handler present, and one is not attached by "the end of the event loop turn", the resulting `(message, url, line, column, error, promise)` tuple will hit `window.onerror`. If the developer subsequently attaches a rejection handler to that promise, then the `promise` object will be passed to any handlers for the `rejectionhandled` event. As usual, if
Re: [whatwg] An API for unhandled promise rejections
On 9/12/14, 4:07 PM, Domenic Denicola wrote: To state what happens in that scenario more clearly: - `error` is fired at time zero. Nobody is listening. - `rejectionhandled` is fired at time 200 ms. Somebody is listening, and "got here" is logged. OK, good. We're on the same page! -Boris
Re: [whatwg] An API for unhandled promise rejections
From: whatwg [mailto:whatwg-boun...@lists.whatwg.org] On Behalf Of Boris Zbarsky >> In this case the event would be fired > > By "the" event do you mean the error event or the rejectionhandled event? Ah, trick question! Because, see, I was confused when I wrote that, and myself did not know! >> but no listener would be present at that time, so "got here" would not be >> logged. > > In my mental model based on your initial mail here, the rejectionhandled > event would get fired at the point when catch() is called, which is after > window.onrejectionhandled is set. You are totally right. To state what happens in that scenario more clearly: - `error` is fired at time zero. Nobody is listening. - `rejectionhandled` is fired at time 200 ms. Somebody is listening, and "got here" is logged. So to answer the original question: > If there is no listener for either when the promise would normally fire > error, but then a listener for "rejectionhandled" gets added before a > .catch() call on the promise, does the listener get called? Yes, yes it does. Sorry about the massive confusion. I should probably stop writing emails for the night :).
Re: [whatwg] An API for unhandled promise rejections
On 9/12/14, 3:45 PM, Domenic Denicola wrote: var p = Promise.reject(new Error("boo")); setTimeout(() => { window.onrejectionhandled = () => console.log("got here"); }, 100); setTimeout(() => { p.catch(() => {}); }, 200); That's a good proxy for what I was envisioning... In this case the event would be fired By "the" event do you mean the error event or the rejectionhandled event? but no listener would be present at that time, so "got here" would not be logged. In my mental model based on your initial mail here, the rejectionhandled event would get fired at the point when catch() is called, which is after window.onrejectionhandled is set. The promise itself can't be shipped out of the worker scope to the onerror on the Worker itself; that's why I was asking what we want to do with workers. If we want a unique key thing there we need some non-object (or at least structured clonable) key. Oh, hmm, I didn't realize you could listen to worker errors via `workerInstance.onerror = ...` in the creating script; I thought you were referring to `self.onerror = ...` inside the worker. We have both. self.onerror gets first dibs at the error, and if it doesn't do anything to prevent the error propagating, then workerInstance gets an error event fired at it. More reason for an integer key, I guess. (Call it promiseId, presumably?) The alternative would be not letting you catch such errors via `workerInstance.onerror`, but I assume that would just complicate things and fit poorly with any telemetry frameworks that try to collect errors from both the window and any spawned workers. Yeah, I have no good insights into what, if anything, telemetry frameworks do with error events on workers. -Boris
Re: [whatwg] An API for unhandled promise rejections
From: Boris Zbarsky [mailto:bzbar...@mit.edu] >On 9/12/14, 3:19 PM, Domenic Denicola wrote: >>> If there is no listener for either when the promise would normally fire >>> error, but then a listener for "rejectionhandled" gets added before a >>> .catch() call on the promise, does the listener get called? >> >> No. > > That's not compatible with "the events always get fired", afaict > Are we talking about different situations here somehow? Probably. Some code would help :). I envision the scenario you're describing as: ```js var p = Promise.reject(new Error("boo")); setTimeout(() => { window.onrejectionhandled = () => console.log("got here"); }, 100); setTimeout(() => { p.catch(() => {}); }, 200); ``` In this case the event would be fired, but no listener would be present at that time, so "got here" would not be logged. What scenario were you envisioning? > The promise itself can't be shipped out of the worker scope to the onerror on > the Worker itself; that's why I was asking what we want to do with workers. > If we want a unique key thing there we need some non-object (or at least > structured clonable) key. Oh, hmm, I didn't realize you could listen to worker errors via `workerInstance.onerror = ...` in the creating script; I thought you were referring to `self.onerror = ...` inside the worker. More reason for an integer key, I guess. (Call it promiseId, presumably?) The alternative would be not letting you catch such errors via `workerInstance.onerror`, but I assume that would just complicate things and fit poorly with any telemetry frameworks that try to collect errors from both the window and any spawned workers.
Re: [whatwg] An API for unhandled promise rejections
On 9/12/14, 3:19 PM, Domenic Denicola wrote: If there is no listener for either when the promise would normally fire error, but then a listener for "rejectionhandled" gets added before a .catch() call on the promise, does the listener get called? No. That's not compatible with "the events always get fired", afaict Are we talking about different situations here somehow? This presumably implies keeping the promise alive and not allowing the garbage collector to collect it until that task executes, right? Interesting. This seems OK since it would only be until the queued task executes, which should be very soon. There's no obvious guarantee of that, especially in workers. But if this complicates implementations undesirably, we could fall back to integer IDs or something. The only important thing IMO is being able to match up `error` and `rejectionhandled` occurrences, and to me the promise itself was a good key. The promise itself can't be shipped out of the worker scope to the onerror on the Worker itself; that's why I was asking what we want to do with workers. If we want a unique key thing there we need some non-object (or at least structured clonable) key. -Boris
Re: [whatwg] An API for unhandled promise rejections
From: whatwg [mailto:whatwg-boun...@lists.whatwg.org] On Behalf Of Boris Zbarsky >> As usual, if one or both of these events is missing listeners, nothing will >> happen. > > I'm not sure that's "usual". I think I misspoke here. The events will still be fired! Anything else would be insanity. I just meant that from a developer perspective, nothing important would occur. > Specifically, an observable case that's worth considering: if there is no > listener for "error" but there is a listener for "rejectionhandled", does the > latter get called? Yes. > If there is no listener for either when the promise would normally fire > error, but then a listener for "rejectionhandled" gets added before a > .catch() call on the promise, does the listener get called? No. > It seems to me like from a spec point of view if this sort of thing is done > the events should fire unconditionally instead of depending on whether > listeners exist, like other events in the platform. If there really are no > listeners, such that UA shenanigans are not observable, UAs are free to > perform those shenanigans, whatever they are. Definitely agreed. > Worker globals too, right? Sounds good to me. > What is the resulting interaction with onerror on the worker object itself? > Would we grow an onrejectionhandled attribute on AbstractWorker as well? Yeah, that would make sense to me. > This presumably implies keeping the promise alive and not allowing the > garbage collector to collect it until that task executes, right? Interesting. This seems OK since it would only be until the queued task executes, which should be very soon. But if this complicates implementations undesirably, we could fall back to integer IDs or something. The only important thing IMO is being able to match up `error` and `rejectionhandled` occurrences, and to me the promise itself was a good key. (I might be missing some use cases where the promise comes in handy, but off the top of my head I can't think of one.)
Re: [whatwg] An API for unhandled promise rejections
On 9/12/14, 2:34 PM, Domenic Denicola wrote: Thank you for writing this up. This is definitely an area that needs improvement. As usual, if one or both of these events is missing listeners, nothing will happen. I'm not sure that's "usual". Specifically, an observable case that's worth considering: if there is no listener for "error" but there is a listener for "rejectionhandled", does the latter get called? If there is no listener for either when the promise would normally fire error, but then a listener for "rejectionhandled" gets added before a .catch() call on the promise, does the listener get called? It seems to me like from a spec point of view if this sort of thing is done the events should fire unconditionally instead of depending on whether listeners exist, like other events in the platform. If there really are no listeners, such that UA shenanigans are not observable, UAs are free to perform those shenanigans, whatever they are. We would add a new event to the global, named `rejectionhandled`, along with a `RejectionHandledEvent` class that contains only a `promise` member. Worker globals too, right? What is the resulting interaction with onerror on the worker object itself? Would we grow an onrejectionhandled attribute on AbstractWorker as well? * When a promise is rejected, if it has no handlers, we would queue a task to potentially-fire-an-error. This presumably implies keeping the promise alive and not allowing the garbage collector to collect it until that task executes, right? -Boris P.S. I'm torn on whether to reuse existing onerror mechanisms for this or not...
[whatwg] An API for unhandled promise rejections
## Problem A common desire in web programming is to log any uncaught exceptions back to the server. The typical method for doing this is window.onerror = (message, url, line, column, error) => { // log `error` back to the server }; When programming asynchronously with promises, asynchronous exceptions are encapsulated as _rejected promises_. They can be caught and handled with `promise.catch(err => ...)`, and propagate up through an "asynchronous call stack" (i.e. a promise chain) in a similar manner to synchronous errors. However, for promises, there is no notion of the "top-level" of the promise chain at which the rejection is known to be unhandled. Promises are inherently temporal, and at any time code that has access to a given promise could handle the rejection it encapsulates. Thus, unlike with synchronous code, there is not an ever-growing list of unhandled exceptions: instead, there is a growing and shrinking list of currently-unhandled rejections. For developers to be able to debug promises effectively, this live list of currently-unhandled rejections certainly needs to be exposed via developer tools, similar to how devtools exposes the ever-growing list of unhandled exceptions (via console output). However, developer tools are not sufficient to satisfy the telemetry use case, i.e. the use case which is currently handled via `window.onerror` for synchronous code. ## Proposed Solution We propose that 1. `window.onerror` be extended to handle the rejected-promise use case, notifying about any promises that, "at the end of the task queue", contain rejections that are not yet handled; and 2. A new hook, `window.onrejectionhandled`, be added, to notify when (or if) such rejections eventually become handled. By "at the end of the task queue" I mean that upon a promise being rejected with no handlers, we would queue a task to fire an error event; however if a handler is then attached to a promise in the meantime, a flag would be set so that when the task executes nothing actually happens. ### Developer Experience In terms of developer experience, the result is that if a promise is rejected without any rejection handler present, and one is not attached by "the end of the event loop turn", the resulting `(message, url, line, column, error, promise)` tuple will hit `window.onerror`. If the developer subsequently attaches a rejection handler to that promise, then the `promise` object will be passed to any handlers for the `rejectionhandled` event. As usual, if one or both of these events is missing listeners, nothing will happen. (In this case, the developer likely does not want to do telemetry on errors, but instead will be availing themselves to the devtools.) A robust error-reporting system would use `rejectionhandled` events to cancel out earlier `error` events, never displaying them to the person reading the error report. ### Specification Details We would extend [`ErrorEvent`](http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#the-errorevent-interface) and `ErrorEventInit` with a `promise` member. Similarly, we would extend the [`OnErrorEventHandlerNonNull`](http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#onerroreventhandlernonnull) callback type to take as its last argument that same promise. In both cases, the promise would be `undefined` for synchronous errors. We would add a new event to the global, named `rejectionhandled`, along with a `RejectionHandledEvent` class that contains only a `promise` member. We would need to hook into rejecting promises and `then`-ing promises, and track unhandled rejections: * When a promise is rejected, if it has no handlers, we would queue a task to potentially-fire-an-error. * When a promise is `then`'d (either by user code or by the spec's chaining mechanisms) but the rejection has not yet been reported, we would set a flag saying "don't fire that error after all." * When the task is executed, if that flag is still unset, we would then fire the appropriate `error` event. * If a promise is `then`-ed in such a way as to handle the rejection, but that promise had previously been reported as an unhandled rejection, we would need to fire the appropriate `rejectionhandled` event. I can go into details on how to modify the promises spec to have these hooks, if desired, as well as how HTML would exploit them to maintain the appropriate list and report it at the end of the task queue. I can also help with the spec work here, on both the ES side and the HTML side, if desired. ### Potential Variants The `error` event and its idiosyncratic handler are not the best possible extension points. We may be better off with a separate `unhandledrejection` event (or, more accurately and as [popular libraries](https://github.com/petkaantonov/bluebird/#error-handling) call it, `possiblyunhandledrejection`). We could even unify on a single event class