Re: [WebIDL] Exceptions

On Jul 6, 2011, at 5:05 PM, Jonas Sicking wrote:

> On Wed, Jul 6, 2011 at 2:23 PM, Aryeh Gregor <> wrote:
>> On Wed, Jul 6, 2011 at 7:06 AM, Anne van Kesteren <> wrote:
>>> So with Web IDL going to Last Call does this mean that the exception model
>>> outlined in is the
>>> way forward? I.e. we introduce new exception interfaces in DOM Core for all
>>> the different exception types and update all other specifications that use
>>> DOM Core to dispatch those exceptions instead (and they are somewhat
>>> backwards compatible because they inherit from DOMException and therefore
>>> still have the code member).
>>> I guess there is no particular rush on this; I am mainly wondering whether
>>> other editors are aware of this change and agree with it.
>> The thing I don't like about this proposal is that it encourages
>> authors to use "e instanceof IndexSizeError" or similar.  This will
>> work 98% of the time and then fail in an extremely mysterious way when
>> multiple globals are involved.  All you need is the exception to be
>> thrown by something in an iframe for whatever reason.
>> Moreover, I don't even think behavior in that case is defined.  If I
>> call foo.appendChild(bar) and it throws, is the exception from the
>> window where the method was called, or the one foo is associated with,
>> or the one bar is associated with?  Browsers other than Gecko seem to
>> agree it's the one foo is associated with
>> (<>),
>> and Gecko is just buggy, but is this specced anywhere?  I don't see it
>> in DOM Core.
>> I don't see why we need the extra classes.  What's the advantage over
>> just adding the .name attribute, or something equivalent, and not
>> adding new classes?  Just consistency with ES, or something else too?
> This is indeed a good point. The main reason for me was consistency
> with ES. But I'm not sure why ES was designed the way it is. Generally
> it seems like multiple globals wasn't kept in mind a lot when ES was
> designed, though obviously this is a problem for ES on the web.
> Would love to hear from ES people that surely has spent more time
> thinking about exceptions than me.
> / Jonas

From an Object-oriented design perspective I always discourage use of instanceof tests.  The problem mentioned here by a Aryeh is a good example why, you may have semantically equivalent objects that are instances of different "classes" in different hierarchies.  This is particularly true for dynamic languages such as ES.  Given that DOM Core is explicitly an environment that provides multiple global objects (and hence multiple semantically equivalent objects) it seems particularly unwise for it to depend upon or even recommend using such tests. 

ECMAScript itself does not have a very rich set of exception "classes" and its hierarchy is essentially flat. If you ignore instanceof testing then all the specialized exception constructors (TypeError, RangeError, ReferenceError, etc.) really provide is the ability to say:
     throw RangeError("my message");
instead of
     var excpt = Error("my message"); = "RangeError";
     throw excpt;
In other words, a more concise way to set the name property of a new exception that is about to be thrown.  Given that the various DOMErrors are thrown by the DOM implementation, I don't think that ease of throwing is a relevant issues. 

As a further point of reference I've designed several exception hierarchies for a couple of languages and used them in many others.  My experience is that while some developers love to put time into designing elaborate hierarchies of exceptions, in practice hierarchical exception structures are seldom exploited by actual application code. A few flat exceptions are more useful then a complex hierarchy that nobody ever remembers.

In the case of the the DOM I think a single exception type where different kinds of exceptions are discriminated by their name property would be much better then a bunch of frame dependent exception constructors.

I'd much prefer to see code that looks like:
     try {doSomeDOMStuff() }
     catch (e) {
        switch ( {
             case "NoNotificationAllowedError": ...; break;
             case "HierarchyRequestError": ...; break;
             default: throw e

 rather than:

     try {doSomeDOMStuff() }
     catch (e) {
        if (e instanceof NoNotificationAllowError) {...}
        else if (e instanceof HierarchyRequestError) {...}
       else throw e;

The latter invites cross-frame multiple global issues.  The former is totally immune to them. 

Received on Thursday, 7 July 2011 01:06:56 UTC