- From: Boris Zbarsky <bzbarsky@MIT.EDU>
- Date: Sun, 10 Nov 2013 21:12:57 -0500
- To: es-discuss@mozilla.org, "public-script-coord@w3.org" <public-script-coord@w3.org>
On 11/10/13 8:25 PM, Allen Wirfs-Brock wrote: > Where the usual attempts at describing overloads for JS go wrong is it they either ignore dynamic coercions or forget in in real JS code they would happen after the overload selection. WebIDL address this by building performing (known) coercions into its overload selection algorithm. But I don't think any human JS programer would do it the way it does. So the way WebIDL works right now is basically a 4-step process: 1) Select the set of valid overloads for the given argument count (basically, select all the overloads that might be callable with that many arguments, based on which arguments they have optional, etc). 2) Do dynamic coercions for arguments starting with the first one and up through the last one on which the elements of this set agree. 3) Select the right overload based on the first argument on which the remaining elements of the overload set disagree. 4) Finish doing dynamic coercions. I agree that this is not how anyone would write this in practice. Part of the reason for this is that this algorithm is trying to handle two types of overloading at once: overloading on argument count (step 1) and overloading on type of argument (step 3). And there are complications from dealing with overloads of the "argument type" kind in situations where some of the overloads have (typed!) varargs at the end and whatnot, at least in theory. In practice, though, APIs generally do one or the other but not both. To do both you'd need an API somewhat like this (in WebIDL): void foo(); void foo(InterfaceType1 arg); void foo(InterfaceType2 arg); where some overloads have to be told apart by number of arguments and some have to be told apart by the types of the arguments. I just checked for APIs in Gecko's WebIDL where selection is happening based on argument count (in that there are overloads with different argument counts) and there are also some argument counts which have multiple overloads for them. The upshot is that almost all of them can in fact be dealt with by picking an "overload" based on type of the first argument that doesn't match across all the overloads with just a few exceptions: Document: TouchList createTouchList(Touch... touches); TouchList createTouchList(sequence<Touch> touches); IDBFactory: IDBOpenDBRequest open(DOMString name, [EnforceRange] unsigned long long version); IDBOpenDBRequest open(DOMString name, optional IDBOpenDBOptions options); URL: [Constructor(DOMString url, URL base), Constructor(DOMString url, optional DOMString base = "about:blank")] interface URL { WebSocket: [Constructor(DOMString url), Constructor(DOMString url, DOMString protocols), Constructor(DOMString url, sequence<DOMString> protocols)] XMLHttpRequest: void send(); void send(ArrayBuffer data); void send(ArrayBufferView data); void send(Blob data); void send(Document data); void send(DOMString? data); void send(FormData data); void send(InputStream data); I believe even for all of these, we could treat them as overloads on the "type" of some argument, where we allow "undefined" as a type that matches the argument not being present or an argument being optional. So a viable way forward in terms of WebIDL overloads, perhaps, is to simply disallow overloading on both argument count and argument types (modulo the proviso about undefined above, somehow) and require that overloads for a name either all have an argument that can be used to distinguish them from each other or take different argument counts but not both. Or something. This does nothing for getting rid of the need to check arguments.length in overloads that overload on the arg count, of course. We could be more radical and recast it all in terms of examining types, treating missing arguments as undefined but that would break compat in at least canvas methods, unfortunately, and I don't think we _really_ want to go there. On the other hand, what we probably _could_ do if we make the split above is make overloading on arg count explicitly deprecated (e.g. enforce in UAs that no new APIs that use it get added). -Boris
Received on Monday, 11 November 2013 02:13:27 UTC