- From: Cameron McCormack <cam@mcc.id.au>
- Date: Tue, 23 Aug 2011 11:23:43 +1200
- To: Jonas Sicking <jonas@sicking.cc>
- CC: public-script-coord@w3.org
On 22/07/11 7:22 AM, Jonas Sicking wrote: > dictionary FooOptions { > boolean reverse = false; > unsigned long limit; > }; > > interface Foo { > void someFunc(in DOMString name, optional in FooOptions options); > }; ... > myfoo.someFunc("name", 4); > > The dictionary algorithm will convert the '4' to an object and then > attempt to read properties off that object. However since the object > won't have any properties, all properties in the dictionary will get > their default value. In other words, the above is equivalent to > > myfoo.someFunc("name", {}); > and > myfoo.someFunc("name"); > > It seems to very likely that if someone passes in a non-object, they > have a bug in their code and we would do them a bigger service by > throwing an exception than silently ignoring their argument. I agree. > This does leave the question what to do for something like: > > myfoo.someFunc("name", null); > and > myfoo.someFunc("name", undefined); > > It seems useful to me to allow both these and use the default values > in both cases. For example for code that looks like: > > function myDoStuffFunc(name, options) { > getFooObj().someFunc(name, options); > } At the moment, you could write interface Foo { void someFunc(DOMString name, optional FooOptions? options); }; so that null is a valid value of the second argument, and you write prose handling that case. There's slight utility in allowing null (or undefined) versus { } -- for the cases that Allen brings up where the dictionaries have members whose names are the names of properties from Object.prototype. So I would be OK with changing the rules in #es-dictionary so that null and undefined get converted into empty dictionaries. The trouble though is when considering overloading -- I am not sure that I would want null or undefined to select an operation whose argument type is a dictionary. Currently the overload resolution algorithm does not use undefined to select object-ish types (interface types, "object", dictionaries, array/sequence types). If undefined could be used to select a dictionary type, then I would want to disallow overloading primitive types vs dictionary types, such as dictionary D { }; void f(long x); void f(D x); I just realised this same case applies to Lachy's request to allow undefined to select nullable non-primitive types in the overload resolution algorithm. On my initial thoughts, I would want to refuse that request too, since we already have: interface HTMLSelectElement { ... void add(HTMLOptionElement element, optional HTMLElement? before); void add(HTMLOptionElement element, long before); }; Well, in this case the proposed "treat undefined as missing optional argument" would probably kick in first. What I am trying to do is to limit the situations where you have two distinguishable types, and an ECMAScript value that does not remove one or both of these types during the overload resolution. The only situation where this case comes up at the moment is when you consider multiple interfaces and an object that happens to implement both: void f(Node n); void f(EventTarget t); This is not disallowed in the IDL (per the rules in the Overloading section, since Node and EventTarget are "distinguishable"), but you'll definitely be able to pass an object in that implements both. The spec says currently just to resolve the tie according to prose, or arbitrarily otherwise. This isn't particularly satisfying, but I can live with it. (Recent changes to the spec limit objects to implementing only one IDL interface and all of its inherited/consequential interfaces, so in fact I can probably remove that ambiguous case now.) What I don't want is a case like: void f(long x); void f(Node n); where calling f(undefined) does not disambiguate the call. Currently, all other ECMAScript values that you can pass in as the argument will either disqualify one or both of those calls. With respect to null, currently no types (except for "any") include null in their sets of values. You always have to use "?". I wouldn't want to make null select a dictionary type during overload resolution unless we disallow "DictionaryType?". Otherwise passing null to these two functions would mean slightly different things: void f(DictionaryType d); void g(DictionaryType? d); Here is a proposal then: we define dictionary types not to be distinguishable from primitive types. This would disallow overloading like void f(DictionaryType d); void f(long x); avoiding the problem of what undefined selects. We would leave null out of it, so passing null here would disqualify both calls. You would still be allowed to write "DictionaryType?" if your API wanted to distinguish between an empty dictionary and the null value for whatever reason. Also, the conversion in #es-dictionary would throw for any value that is not an object, null or undefined.
Received on Monday, 22 August 2011 23:24:16 UTC