Re: Notes from Monday's meeting with TC39 folks

On Oct 8, 2009, at 12:25 PM, Jonas Sicking wrote:

> On Wed, Oct 7, 2009 at 10:50 PM, Maciej Stachowiak <mjs@apple.com>  
> wrote:
>>
>> How would you specify canvas's getImageData() with this approach? Or
>> drawImage()? Seems like it is impossible to specify the interface  
>> correctly
>> with the union type mechanism. It's one thing to "discourage", but  
>> if IDL
>> can't specify the behavior of existing interfaces, then it will  
>> fail in its
>> purpose.
>
> I definitely agree that union types + [optional] provides less
> expressiveness than overloading. For example you can't say that a
> function can only take 0 or 2 floats. Or can only take one two floats
> or an ImageData (like CanvasRenderingContext2D.createImageData).
>
> However you can always describe that in prose. We'll never have a IDL
> language that can express all the needed constraints. For example the
> ability to say that a float argument must be non-negative, or non-NaN,
> or say that if a boolean argument is missing it should default to
> 'true'. It'll always be a judgement call what to allow IDL to express,
> and what needs to be put in prose. For example the IDL for
> CanvasRenderingContext2D.drawImage might actually be easier to
> understand if it was expressed in prose. It currently has 6 overloads,
> half of which has [optional] arguments.

Anything that's in prose but reasonably could be in the IDL without  
adding undue complexity is a lost opportunity. Because then we either  
have to hand-write the binding, or we have to invent our own syntax to  
get the IDL compiler to do it.

>
> One possible place to draw the line is how much you'd want a
> scripting<->C++ conversion layer to support. For example, would you
> expect such a layer to enforce all of the requirements for drawImage?

I would expect it to enforce the type requirements and dispatch to the  
right internal version of the method, yes.

> In gecko we currently only have one drawImage function in our internal
> IDL which the conversion layer always dispatches to, that function
> then does all the checking.
>
> It's possible that other conversion layers would do things differently
> (in fact, i'd be surprised if that wasn't the case). And there's
> definitely other ways to draw the line for what goes into the IDL.

What we strive for in WebKit is to have generated code do the type  
checking and conversion of incoming JS values, and then dispatch to a  
core implementation in C++ which can also be bound (via codegen from  
IDL) to other languages such as Objective-C or Python. We don't want  
to make the core methods depend on implementation details of the  
JavaScript engine in any way.

>>>
>>> With regards to how the undefined value should be coerced to a  
>>> string,
>>> Jonas said (paraphrasing):
>>>
>>>  A lot of people have argued that we should always use the String
>>>  constructor so undefined gets converted to "undefined" (and  
>>> similarly
>>>  for null).  I see logic in that too.  What makes the least amount  
>>> of
>>>  sense is what we do in Gecko, where null comes "" and undefined
>>>  becomes "undefined".  I think we should recommend converting both  
>>> to
>>>  the empty string and seeing what people say.  We can use union  
>>> types
>>>  to handled undefined differently if necessary.  I think IE  
>>> generally
>>>  stringifies both null and undefined.
>>
>> Many of the DOM Core and DOM Events interfaces specifically mandate  
>> treating
>> null the same as the empty string, and in at least some cases this  
>> works
>> interoperably.
>>
>> I think changing the behavior for undefined could be a  
>> compatibility risk.
>
> I'd be very interested to gather data here. I suspect that *in
> general* null and undefined are rarely passed to these functions, so I
> think we're a little free to play around with behavior here. There are
> exceptions of course, for example I suspect treating null as "null" in
> the namespaceURI argument for setAttributeNS would break the web.

I would expect they are passed accidentally often enough to matter.  
Because any way you can abuse an API, some Web content is doing it, as  
long as it seems to work for their purposes.

> While Gecko by default treats null as the empty string, I was under
> the impression that most (all?) other major UAs by default treat null
> as "null". And that for example WebKit used IDL extended attributes
> for when to treat null as "". (This is one of the reasons I suspect
> people don't generally depend on behavior here.)

That's right, but over time we've changed more and more places in our  
IDL to treat null as "". Our plan is to eventually flip the default.

>
> If so, where do you end up having to explicitly treat null as ""?
>
> As for undefined, I think UAs fairly consistently treat that as  
> "undefined".

Yes, in almost all places I think. I did find a few methods where  
WebKit will treat undefined as an empty string, I am not sure how many  
of these are essential however. Examples include  
DOMImplemenation.createDocument(), Window.prompt(),  
setCustomValidity() on form controls.

>
> If it turns out that WebKit only in a few places end to treating null
> as "", then I think we should make the default to use the String
> constructor for all DOMString arguments, and in the few cases where
> null needs to be treated as "", annotate that in the IDL. If that
> annotation is done as a "DOMString | null", "DOMString?", or
> "[Null=''] DOMString" I care less about.
>
> If it turns out we have to annotate the exception in a lot of places,
> my second preferred option would be to treat both null and undefined
> as "", unless annotated differently.
>
>>> And Mark said:
>>>
>>>  We shouldn’t be considering converting null to "" but undefined to
>>>  "undefined".
>>
>> But that's what most browsers do for most existing DOM APIs (with  
>> quirky
>> exceptions). So we must consider it.
>
> I agree we should consider it.
>
>>> Later discussion, assuming that there was no Undefined type in the  
>>> IDL,
>>> suggested that the Null IDL type could be specified as either null  
>>> or
>>> undefined in ES, but when returned from the implementation to ES  
>>> would
>>> always be denoted using null.
>>
>> Since null and undefined are often treated differently, this seems  
>> like a
>> bad idea.
>
> Really? And how do you mean "treated differently". For strings, see
> discussion above, too many unknowns at this point for me to give a
> firm answer. For objects, it seems like at least gecko treats
> undefined as null, need to check other UAs.

I mean when passed as strings. As numbers, undefined converts to NaN  
and null converts to 0. I haven't done testing or study of object  
parameters yet.

> There's also things like pushState, which takes an "any" argument
> which is then cloned using the "structured clone" algorithm. Here I
> agree that null and undefined needs to be treated differently in the
> sense that null should be cloned to null and undefined to undefined.

Indeed.

>> Yuck. Many DOM APIs can return null, having to annotate all of them  
>> seems
>> like a lot of work for low return.
>
> I think we currently have a problem where lots of functions take
> objects, but do not define behavior when null is passed in. I'd like
> to fix this by making it explicit in the IDL when null is an
> acceptable in-value, and in WebIDL define what exception is thrown if
> null is passed in where not allowed. Just like WebIDL should describe
> what exception to pass to a function that takes a Node but is passed a
> string.

In cases where DOM APIs already throw an exception when passed null  
for an object parameter, is it consistently the same exception?

>
>>> Those of us who were able to stay until the end of the meeting  
>>> (all but
>>> Allen) were happy with a few initial recommendations, but I
>>> unfortunately don’t have a note of them.  I believe they included:
>>>
>>>  * Not allowing callable objects in future APIs
>>
>> If it's allowed, it's allowed - at best we can say it SHOULD NOT be  
>> used in
>> new APIs. I don't think it would be appropriate to grandfather in  
>> specific
>> interfaces from other specs by name, and a requirement that doesn't  
>> name the
>> specific interfaces would have no teeth.
>
> Gecko only supports callable on the document.all collection. I'm fine
> with attempting to remove that and see how much people complain. I've
> never heard anyone ask for callability on other collections.
>
> Microsoft is apparently looking into if they can remove callable.
>
> I'd say lets not put callable into the specifications. UAs are always
> free to implement additional features that aren't in the spec,
> everyone already does. Once we've tried to remove callable and it
> turns out to break the web we can always add it to the spec then.

I'd rather we remove it from the spec after we determine that it can  
safely be removed and that everyone is on board with this. Just  
leaving it undefined is a cop-out.

What I think makes more sense in the short term is to move callability  
to supplemental interfaces in the Obsolete section, as HTML5 does for  
IDL attributes that reflect obsolete content attributes. That puts it  
out of view of authors, but makes the implementation behavior well- 
defined.

And finally, I don't think callability on random objects is even that  
bad. It doesn't violate deep design assumptions of ECMAScript for  
objects to be callable without being a Function. There's even cases  
where it might be a reasonable API (it does seem a bit icky for  
collections, admittedly). It doesn't get in your way if you don't use  
it or know about it, unlike property catchalls. It doesn't seem like  
its worth a huge effort to try to purge it from the platform.

Regards,
Maciej

Received on Thursday, 8 October 2009 19:57:19 UTC