Re: [WebIDL] Handling undefined in Overload Resolution Algorithm

On Thu, Aug 4, 2011 at 4:01 AM, Cameron McCormack <cam@mcc.id.au> wrote:
> Lachlan Hunt:
>> No, this is not always true for all methods.  Consider:
>
> I was a bit worried about something like this, but didn’t think it
> through.
>
>> document.write() // writes nothing
>> document.write(undefined) // writes "undefined"
>>
>> Although this particular case isn't overloaded, so the overload
>> resolution algorithm won't be run.
>
> Actually, I did recently remove the different behaviour between
> overloaded and non-overloaded operation invocation.  So it does look
> like treating undefined the same as omitting the argument entirely does
> not work across the board.

window.alert() probably has the same issue.

But if document.write and window.alert are the only examples of this,
I don't think we need to adjust all of WebIDL to it. It's easy enough
to describe this exception in prose.

>> >* Anywhere an undefined would help select a nullable primitive type
>> >during overload resolution, it should help select nullable types
>> >regardless of the inner type. (This would still matter in cases
>> >where explicit undefined is passed in the middle of the argument list,
>> >and later arguments are not undefined.)
>>
>> Is that intended to handle this case?
>>
>> e.g. consider a function
>>
>> void f(in DOMString x, in DOMString y, in DOMString z);
>>
>> f("a", undefined, "c")
>>
>> This should not throw a type error, even if the function is overloaded.
>
> Looking at how the overload resolution algorithm currently works, it
> looks at each argument position across all of the overloads for a given
> argument list length, and if it’s not the case that all the types are
> the same at that position, then it uses the ECMAScript value passed in
> to discriminate between them.  So in the case where you just have that
> single ‘f’ operation above, it wouldn’t throw due to not finding an
> overload, and undefined would get converted to a DOMString as you
> expect.
>
> If however you had
>
>  void f(in DOMString x, in DOMString y, in DOMString z);
>  void f(in DOMString x, in float y, in DOMString z);
>
> and you called `f("a", undefined, "b")`, then it would use undefined to
> help distinguish between those two, and it would choose the second one.

Out of curiosity, why the second?

>> >And finally for the API at hand:
>> >
>> >Element querySelector(in DOMString a, in optional Element b);
>> >Element querySelector(in DOMString a, in sequence<Node>? b);
>> >
>> >Overloads are:
>> >(DOMString)
>> >(DOMString, Element)
>> >(DOMString, sequence<Node>?)
>> >
>> >querySelector(undefined) === throw TypeError
>>
>> No, I don't think that one should throw a type error.  Right now, it
>> stringifies to "undefined" in implementations and doesn't throw.
>
> OK.  So treating querySelector(undefined) as a zero argument call
> doesn’t work here (in conjunction with throwing for too few arguments).
>
> Will think about it more tomorrow…

I think we should only treat <undefined> as "not specified" for
optional arguments. For required arguments it would seem like using
the normal coercion algorithm makes the most sense.

If for no other reason, otherwise it's impossible to specify a function like

  void foo(in any a);

and be able to call that with

x.foo(undefined);

This is something that is needed by at least IndexedDB and postMessage.

/ Jonas

Received on Thursday, 4 August 2011 23:52:10 UTC