domenic at domenicdenicola.com (2013-07-19T15:56:10.184Z)
I think we have the following constraints for exceptions thrown by the DOM: ```js x instanceof DOMException ``` This *probably* needs to evaluate to true. ```js x.code == DOMException.HIERARCHY_REQUEST_ERR x.code == 3 ``` This definitely needs to evaluate to true for a bunch of older APIs. This used to be the only way to test what type of exception you had. For newer exception types we haven't added a code and so .code returns 0. For those APIs you use .name instead, see below. Obviously the exact constant and number varies with the exception type. ```js x.name == "HierarchyRequestError" ``` This should test true. This should be uncontroversial enough that I don't think it matters how much dependency there is, right? Obviously the exact value varies with the exception type. ```js x.message ``` This probably needs to contain a human readable error message. This should be uncontroversial enough that I don't think it matters how much dependency there is, right? ```js Object.toString(x) ``` I *don't* think it's important what this returns. I.e. I would guess that we can safely subclass DOMException as needed. I think we have the following constraints for properties that contain error information in APIs that currently use DOMError (IDBTransaction.error in the IndexedDB spec for example). ```js x instanceof DOMError ``` Probably doesn't matter what this returns. ```js x.name = "AbortError" ``` This should be uncontroversial enough that I don't think it matters how much dependency there is, right? ```js x.message ``` This probably needs to contain a human readable error message. This should be uncontroversial enough that I don't think it matters how much dependency there is, right? ```js Object.toString(x) ``` Probably doesn't matter what this returns. I doubt that in either case it matters if these properties live on the objects themselves, or on the prototype chain. So all in all, I think we have a lot of room for what to do in both cases. The only requirements is that exceptions *likely* need to test true for `instanceof DOMException`, and that they in some cases need to have a specific numeric code property. My recommendation would be to * Get rid of DOMError and use DOMException in its place * Add new subclasses for each exception type. I.e. exceptions with `.name == HierarchyRequestError` should also test true for `instanceof HierarchyRequestError` * Keep specifying that DOMException is a subclass of Error. This is already the case, but I wanted to make it clear that this shouldn't change. I personally think that the second bullet is a bit silly. But since that appears to be the convention that ES uses then we should stick with it.
On Wed, Jul 10, 2013 at 11:49 PM, Mark S. Miller <erights at google.com> wrote: > Hi Jonas, > > The perpetual hazard with trying to clean things up is, of course, legacy > compat constraints. Regarding ES itself, many of those on this list > (including myself) feel oriented about when and where these bite and how > much, and have successfully navigated through these to many successful > cleanups. We have also succeeded at not wasting too much time on attractive > cleanups whose adoption was doomed because of these constraints. > > Regarding DOM, I am certainly less oriented and I suspect at least some > others on this list are too. In the absence of knowledge, it is tempting to > imagine the worst and despair of cleaning up anything that is already > deployed. Could you give a summary -- necessarily subjective which is fine > -- of how you think about what can and cannot be successfully cleanup up > here? Thanks. I think we have the following constraints for exceptions thrown by the DOM: x instanceof DOMException This *probably* needs to evaluate to true. x.code == DOMException.HIERARCHY_REQUEST_ERR x.code == 3 This definitely needs to evaluate to true for a bunch of older APIs. This used to be the only way to test what type of exception you had. For newer exception types we haven't added a code and so .code returns 0. For those APIs you use .name instead, see below. Obviously the exact constant and number varies with the exception type. x.name == "HierarchyRequestError" This should test true. This should be uncontroversial enough that I don't think it matters how much dependency there is, right? Obviously the exact value varies with the exception type. x.message This probably needs to contain a human readable error message. This should be uncontroversial enough that I don't think it matters how much dependency there is, right? Object.toString(x) I *don't* think it's important what this returns. I.e. I would guess that we can safely subclass DOMException as needed. I think we have the following constraints for properties that contain error information in APIs that currently use DOMError (IDBTransaction.error in the IndexedDB spec for example). x instanceof DOMError Probably doesn't matter what this returns. x.name = "AbortError" This should be uncontroversial enough that I don't think it matters how much dependency there is, right? x.message This probably needs to contain a human readable error message. This should be uncontroversial enough that I don't think it matters how much dependency there is, right? Object.toString(x) Probably doesn't matter what this returns. I doubt that in either case it matters if these properties live on the objects themselves, or on the prototype chain. So all in all, I think we have a lot of room for what to do in both cases. The only requirements is that exceptions *likely* need to test true for "instanceof DOMException", and that they in some cases need to have a specific numeric code property. My recommendation would be to * Get rid of DOMError and use DOMException in its place * Add new subclasses for each exception type. I.e. exceptions with .name == HierarchyRequestError should also test true for "instanceof HierarchyRequestError" * Keep specifying that DOMException is a subclass of Error. This is already the case, but I wanted to make it clear that this shouldn't change. I personally think that the second bullet is a bit silly. But since that appears to be the convention that ES uses then we should stick with it. / Jonas > On Wed, Jul 10, 2013 at 8:31 PM, Jonas Sicking <jonas at sicking.cc> wrote: >> >> >> On Jul 10, 2013 3:49 PM, "Erik Arvidsson" <erik.arvidsson at gmail.com> >> wrote: >> > >> > Jonas, DOM never throws DOMError. DOMErrors are used for other error >> > mechanisms, such as callbacks. [1] >> >> Indeed. But this is one of the things I'm trying to fix. It seems very >> silly that the DOM defines two classes of error objects. Neither of which >> are following the patterns used by ES. >> >> / Jonas >> >> > >> > The DOM spec does however throw DOMException objects [2]. These are >> > instanceof Error (see WebIDL [3]) >> > >> > var ex; >> > try { >> > document.appendChild(document); >> > } catch (e) { >> > ex = e; >> > } >> > assert(ex instanceof Error); >> > assert(ex.contructor === DOMException); >> > assert(ex.name === 'HierarchyRequestError'); >> > >> > In Blink DOMException also have a stack property >> > assert(stack in ex); >> > >> > [1] http://dom.spec.whatwg.org/#interface-domerror >> > [2] http://dom.spec.whatwg.org/#exception-domexception >> > [3] >> > http://dev.w3.org/2006/webapi/WebIDL/#es-exception-interface-prototype-object >> > >> > On Wed, Jul 10, 2013 at 3:02 PM, Jonas Sicking <jonas at sicking.cc> wrote: >> > > On Wed, Jul 10, 2013 at 12:52 PM, Domenic Denicola >> > > <domenic at domenicdenicola.com> wrote: >> > >> Woah, François, that seems pretty overcomplicated; why not replace >> > >> everything inside the constructor with `this.message = message`? It has the >> > >> same effect in the browsers I've seen. (Also don't forget >> > >> `SomeError.prototype.constructor = SomeError`.) >> > >> >> > >> Anyway, to Jonas's point: I think `DOMError` is actually pretty OK. >> > >> One thing I noticed is that the ES5 spec (and presumably ES6, although I >> > >> haven't checked) is careful to never throw simple `Error` objects, but >> > >> instead `TypeError`s or `RangeError`s or so on. I infer that they are >> > >> leaving bare `Error` for user cases. I think "the platform" should generally >> > >> follow this lead; that is, the DOM should leave bare `Error`s to the user, >> > >> and throw `DOMError`s or `TypeError`s or `RangeError`s for its own errors. >> > >> >> > >> To answer your more general question, authors are strongly >> > >> discouraged from ever throwing anything that is not `instanceof Error`, see >> > >> e.g. Guillermo Rauch's [A String is not an >> > >> Error](http://www.devthought.com/2011/12/22/a-string-is-not-an-error/). >> > >> Also, the `name` property is generally the same across all instances of a >> > >> particular error type, i.e. >> > >> >> > >> ```js >> > >> errInstance.name === errInstance.constructor.name === >> > >> errInstance.constructor.prototype.name === >> > >> Object.getPrototypeOf(errInstance).name >> > >> ``` >> > >> >> > >> (You can verify this for all the built-in ES5 errors.) Usually a >> > >> `code` property is used for more specific information, from what I've seen. >> > >> But yes, that has to be added manually with a bit of awkwardness, i.e. >> > >> >> > >> ```js >> > >> const e = new DOMError("The message"); >> > >> e.code = "TimeoutError"; >> > >> throw e; >> > >> ``` >> > > >> > > Note that >> > > >> > > (new DOMError) instanceof Error; >> > > >> > > returns false. So the DOM does do the "strongly discouraged" thing. Is >> > > this ok or bad? >> > > >> > > Also, the DOM does not create a new class for each different value of >> > > .name. >> > > >> > > I.e. you can get a DOMError whose .name is "NetworkError" or >> > > "AbortError". DOMError even has a constructor which allows setting >> > > .name to anything: new DOMError(name, message); >> > > >> > > In fact, there are no defined situations where the DOM creates >> > > DOMError objects whose .name is "DOMError". >> > > >> > > Again, is this ok or is it bad practice? >> > > >> > > / Jonas >> > > _______________________________________________ >> > > es-discuss mailing list >> > > es-discuss at mozilla.org >> > > https://mail.mozilla.org/listinfo/es-discuss >> > >> > >> > >> > -- >> > erik >> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> > > > > -- > Cheers, > --MarkM On Wed, Jul 10, 2013 at 8:49 PM, Mark S. Miller <erights at google.com> wrote: > Hi Jonas, > > The perpetual hazard with trying to clean things up is, of course, legacy > compat constraints. Regarding ES itself, many of those on this list > (including myself) feel oriented about when and where these bite and how > much, and have successfully navigated through these to many successful > cleanups. We have also succeeded at not wasting too much time on attractive > cleanups whose adoption was doomed because of these constraints. > > Regarding DOM, I am certainly less oriented and I suspect at least some > others on this list are too. In the absence of knowledge, it is tempting to > imagine the worst and despair of cleaning up anything that is already > deployed. Could you give a summary -- necessarily subjective which is fine > -- of how you think about what can and cannot be successfully cleanup up > here? Thanks. > > > > > On Wed, Jul 10, 2013 at 8:31 PM, Jonas Sicking <jonas at sicking.cc> wrote: >> >> >> On Jul 10, 2013 3:49 PM, "Erik Arvidsson" <erik.arvidsson at gmail.com> >> wrote: >> > >> > Jonas, DOM never throws DOMError. DOMErrors are used for other error >> > mechanisms, such as callbacks. [1] >> >> Indeed. But this is one of the things I'm trying to fix. It seems very >> silly that the DOM defines two classes of error objects. Neither of which >> are following the patterns used by ES. >> >> / Jonas >> >> > >> > The DOM spec does however throw DOMException objects [2]. These are >> > instanceof Error (see WebIDL [3]) >> > >> > var ex; >> > try { >> > document.appendChild(document); >> > } catch (e) { >> > ex = e; >> > } >> > assert(ex instanceof Error); >> > assert(ex.contructor === DOMException); >> > assert(ex.name === 'HierarchyRequestError'); >> > >> > In Blink DOMException also have a stack property >> > assert(stack in ex); >> > >> > [1] http://dom.spec.whatwg.org/#interface-domerror >> > [2] http://dom.spec.whatwg.org/#exception-domexception >> > [3] >> > http://dev.w3.org/2006/webapi/WebIDL/#es-exception-interface-prototype-object >> > >> > On Wed, Jul 10, 2013 at 3:02 PM, Jonas Sicking <jonas at sicking.cc> wrote: >> > > On Wed, Jul 10, 2013 at 12:52 PM, Domenic Denicola >> > > <domenic at domenicdenicola.com> wrote: >> > >> Woah, François, that seems pretty overcomplicated; why not replace >> > >> everything inside the constructor with `this.message = message`? It has the >> > >> same effect in the browsers I've seen. (Also don't forget >> > >> `SomeError.prototype.constructor = SomeError`.) >> > >> >> > >> Anyway, to Jonas's point: I think `DOMError` is actually pretty OK. >> > >> One thing I noticed is that the ES5 spec (and presumably ES6, although I >> > >> haven't checked) is careful to never throw simple `Error` objects, but >> > >> instead `TypeError`s or `RangeError`s or so on. I infer that they are >> > >> leaving bare `Error` for user cases. I think "the platform" should generally >> > >> follow this lead; that is, the DOM should leave bare `Error`s to the user, >> > >> and throw `DOMError`s or `TypeError`s or `RangeError`s for its own errors. >> > >> >> > >> To answer your more general question, authors are strongly >> > >> discouraged from ever throwing anything that is not `instanceof Error`, see >> > >> e.g. Guillermo Rauch's [A String is not an >> > >> Error](http://www.devthought.com/2011/12/22/a-string-is-not-an-error/). >> > >> Also, the `name` property is generally the same across all instances of a >> > >> particular error type, i.e. >> > >> >> > >> ```js >> > >> errInstance.name === errInstance.constructor.name === >> > >> errInstance.constructor.prototype.name === >> > >> Object.getPrototypeOf(errInstance).name >> > >> ``` >> > >> >> > >> (You can verify this for all the built-in ES5 errors.) Usually a >> > >> `code` property is used for more specific information, from what I've seen. >> > >> But yes, that has to be added manually with a bit of awkwardness, i.e. >> > >> >> > >> ```js >> > >> const e = new DOMError("The message"); >> > >> e.code = "TimeoutError"; >> > >> throw e; >> > >> ``` >> > > >> > > Note that >> > > >> > > (new DOMError) instanceof Error; >> > > >> > > returns false. So the DOM does do the "strongly discouraged" thing. Is >> > > this ok or bad? >> > > >> > > Also, the DOM does not create a new class for each different value of >> > > .name. >> > > >> > > I.e. you can get a DOMError whose .name is "NetworkError" or >> > > "AbortError". DOMError even has a constructor which allows setting >> > > .name to anything: new DOMError(name, message); >> > > >> > > In fact, there are no defined situations where the DOM creates >> > > DOMError objects whose .name is "DOMError". >> > > >> > > Again, is this ok or is it bad practice? >> > > >> > > / Jonas >> > > _______________________________________________ >> > > es-discuss mailing list >> > > es-discuss at mozilla.org >> > > https://mail.mozilla.org/listinfo/es-discuss >> > >> > >> > >> > -- >> > erik >> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> > > > > -- > Cheers, > --MarkM