Jonas Sicking (2013-07-16T23:30:49.000Z)
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
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.