Re: [geometry] Dictionary argument for DOMQuad constructor

Following Simon's move to public-fx; please respond in this thread, not 
the other one...

On 3/24/15 4:35 PM, Simon Pieters wrote:
> [Constructor(optional DOMPointInit p1, optional DOMPointInit p2,
>               optional DOMPointInit p3, optional DOMPointInit p4),
>   Constructor(optional DOMRectInit rect),
....
> * All arguments are optional. This is invalid WebIDL since it's not
> possible to distinguish which constructor to use. For other constructors
> I've let the dictionary be optional and have the other constructor have
> two required arguments. We can do that here as well.

This is exciting.  DOMRectInit and DOMPointInit are both dictionaries, 
right?

WebIDL has this bit:

   If the type of an argument is a dictionary type or a union type that
   has a dictionary type as one of its flattened member types, and this
   argument is either the final argument or is followed only by optional
   arguments, then the argument MUST be specified as optional.

which means that at the moment the constructor version that takes 4 
DOMPointInit arguments must in fact have them all be optional.  So you 
can't do what you propose as things stand.

While that requirement about having trailing dictionary arguments be 
optional makes sense for dictionaries used as options objects (where 
lack of the options object really had better be equivalent to passing {} 
in terms of API design), it doesn't really make much sense here, because 
these arguments aren't really options objects.  In fact, if I saw 
someone doing this:

   new DOMQuad({}, {}, {}, {});

I would be pretty confused...

One plausible approach here would be to make the Web IDL spec change 
proposed in https://www.w3.org/Bugs/Public/show_bug.cgi?id=27953 and 
then make the members of DOMPointInit required and the DOMPointInit 
arguments non-optional.

But it's also worth running this whole idea by someone familiar with JS 
API design.  The overload setup being proposed is basically relying on 
arguments.length to disambiguate which constructor was meant.  How would 
JS code normally handle this situation?  Possibly via arguments.length, 
but possibly via testing the first argument to see whether it has a 
.width property or whatever...

> * If one does `new DOMQuad(other_domquad)`, it will convert the object
> to a DOMRectInit and result in the same thing as `new DOMQuad({})` which
> is probably not what was intended. Supporting two kinds of dictionaries
> is not straightforward, though, since I think WebIDL doesn't distinguish
> between different dictionaries.

Right, because they're all just objects and there's no really principled 
way to do it.  You could distinguish in prose, of course, at the expense 
of having to decide _how_ to distinguish and writing the prose.  Either 
via your proposal of having a dictionary that's the union of the two 
dictionaries, or by making the argument be "object" and doing the 
conversions to dictionary by hand.

Of course if you're doing that, you could just write it as:

   Constructor(optional DOMPointOrRectOrQuadInit arg1,
               optional DOMPointInit p2,
               optional DOMPointInit p3, optional DOMPointInit p4)

and then the prose would see which members of arg1 are present and if so 
decide whether to throw or look at p2-p4 or what.

-Boris

Received on Tuesday, 24 March 2015 20:57:12 UTC