Re: overload resolution consistency

On Tue, 06 Dec 2011 05:06:18 +0100, Cameron McCormack <cam@mcc.id.au>  
wrote:

> At TPAC, we discussed how the behaviour of existing scripts could change  
> when overloads are added to an existing interface.  That's because when  
> there is no overloading, any type of value passed as an argument to an  
> operation will be coerced to the correct type, but when there is  
> overloading, if the type is not correct an exception will be thrown.
>
> For example, with:
>
>    interface A {
>      void f(float x);
>    };
>
> calling f({}) is treated the same as calling f(NaN).  But if later on an  
> overload is introduced:
>
>    interface A {
>      void f(float x);
>      void f(DOMString x);
>    };
>
> then the call f({}) will throw a TypeError.
>
> The suggestion was made during the meeting to make the second case not  
> throw, but fall back to selecting the first operation listed on the  
> interface.  That would make f({}) be the same as f(NaN) again.  People  
> in the room seemed happy with this change.
>
> There is a problem though, which is what to do when you have some  
> matching types and some mismatching.  For example with:
>
>    interface B {
>      void f(object x, object y);
>      void f(float x, DOMString y);
>      void f(float x, float y);
>      void f(DOMString x, float y);
>    };
>
> when you call f("", ""), which overload should be selected and why?
>
> The simplest choice is probably to select the exactly matching overload  
> if there is one, otherwise to select the first overload regardless of  
> the types of the actual arguments.  So for the above example that would  
> select f(object, object).
>
> A less simple choice would be, if there is no exact match, to do some  
> sort of counting or scoring of how well the arguments matched, and to  
> select the first overload with the highest score.  So maybe you would  
> say that you get 1 point for every matched types, resulting in f(float,  
> DOMString) and f(DOMString, float) both scoring 1, and then you choose  
> the first of these two in order of appearance.
>
> Simpler sounds better to me, so I'll choose that unless there are some  
> good reasons not to.

interface HTMLOptionsCollection : HTMLCollection {
   void add(HTMLOptionElement element, optional HTMLElement? before);
   void add(HTMLOptGroupElement element, optional HTMLElement? before);
   void add(HTMLOptionElement element, long before);
   void add(HTMLOptGroupElement element, long before);

(HTMLFormElement also has these variants.)

Consider:

options.add(document.createElement('optgroup'), "foo");

(maybe the second argument comes from an <input type=number> and the  
author forgot to convert it from a string to an int.)


interface CanvasRenderingContext2D {
   CanvasPattern createPattern(HTMLImageElement image, DOMString  
repetition);
   CanvasPattern createPattern(HTMLCanvasElement image, DOMString  
repetition);
   CanvasPattern createPattern(HTMLVideoElement image, DOMString  
repetition);
   void drawImage(HTMLImageElement image, double dx, double dy);
   void drawImage(HTMLImageElement image, double dx, double dy, double dw,  
double dh);
   void drawImage(HTMLImageElement image, double sx, double sy, double sw,  
double sh, double dx, double dy, double dw, double dh);
   void drawImage(HTMLCanvasElement image, double dx, double dy);
   void drawImage(HTMLCanvasElement image, double dx, double dy, double dw,  
double dh);
   void drawImage(HTMLCanvasElement image, double sx, double sy, double sw,  
double sh, double dx, double dy, double dw, double dh);
   void drawImage(HTMLVideoElement image, double dx, double dy);
   void drawImage(HTMLVideoElement image, double dx, double dy, double dw,  
double dh);
   void drawImage(HTMLVideoElement image, double sx, double sy, double sw,  
double sh, double dx, double dy, double dw, double dh);

Consider using a <canvas> or <video> in the first argument, but using the  
wrong type in another argument.

How does it work when there are different number of arguments?

   ImageData createImageData(double sw, double sh);
   ImageData createImageData(ImageData imagedata);

[NoInterfaceObject]
interface WindowTimers {
   long setTimeout(Function handler, optional long timeout, any... args);
   long setTimeout([AllowAny] DOMString handler, optional long timeout,  
any... args);
   long setInterval(Function handler, optional long timeout, any... args);
   long setInterval([AllowAny] DOMString handler, optional long timeout,  
any... args);

This already uses [AllowAny], so the wrong type on the first argument  
would convert to DOMString. But what if the second argument is of the  
wrong type?

interface WebSocket : EventTarget {
   void send(DOMString data);
   void send(ArrayBuffer data);
   void send(Blob data);

This should probably convert to DOMString for other types.

The above extracts are the overloads I found in the HTML spec. What they  
have in common is that the first argument is more important than the other  
arguments, such that we should try not to convert the first argument if  
it's of a matching type.

-- 
Simon Pieters
Opera Software

Received on Tuesday, 6 December 2011 08:47:04 UTC