Re: Nullable interface members (which cannot be initialized to null by the script)

On 2013-12-12 20:13, Jan-Ivar Bruaroey wrote:
> On 12/8/13 11:27 AM, Harald Alvestrand wrote:
>> On 12/05/2013 11:11 AM, Adam Bergkvist wrote:
>>> Hi
>>>
>>> We have a few cases in the spec where interfaces have nullable
>>> attributes, but the dictionaries used to initiate these attributes
>>> don't have nullable types for the corresponding dictionary members.
>>>
>>> I guess the platform could create an object by bypassing the
>>> dictionary (and set a value of null), but I think that should be an
>>> exception.
>>
>> Sorry, I don't understand the problem.
>>
>> The dictionary specification (
>> http://heycam.github.io/webidl/#idl-dictionaries ) says:
>>
>> On a given dictionary value, the presence of each dictionary member is
>> optional.
>>
>> If a dictionary member used to initialize an attribute is not present,
>> it seems to me that the value MUST be null unless the spec says otherwise.
>
> The object can do whatever it wants. It can be undefined. If we want the
> default to be null then the spec should specify a default value of null.
> But I get your larger point below.
>
>> I'm actually worried about the opposite problem: Since events (and
>> other things) are initialized from dictionaries, we seem to have no
>> syntax to express that a certain field MUST be given a value (such as
>> the stream in MediaStreamEvent). But I guess we can express that in prose.
>
> If the prose mandates that the UA throw on missing input, then yes this
> lets us remove the '?'s.
>
> Or better, make the stream a required non-nullable parameter of the
> constructor:
>
>    [ Constructor (DOMString type, MediaStream stream, optional
> MediaStreamEventInit eventInitDict)]
>

I think this is the way to go. We're already using the pattern with 
arguments for mandatory initializations (type) and dictionary for 
optional ones with our current constructor signature.

Since (MediaStreamEventInit - "MediaStream member") = EventInit,
is guess we get:

[ Constructor (DOMString type, MediaStream stream, optional EventInit 
eventInitDict)]

> To transition people over, we'd use a kludge for a while (and warn in
> web console about deprecated use):
>
>    [ Constructor (DOMString type, (MediaStream or MediaStreamEventInit
> streamOrDict), optional MediaStreamEventInit eventInitDict)]
>
> Then remove the kludge(s) in a couple of months.
>
>> But looking at your examples, I do have opinions for each....
>>> Looking at the first one - I don't think we want a MediaStreamEvent
>>> with a null-MediaStream that would need a not-null-check before it
>>> can be used. Are any of the other motivated or should I remove the
>>> "?" from the attributes from all of them?
>>>
>>> /Adam
>>>
>>> dictionary MediaStreamEventInit : EventInit {
>>>     MediaStream stream;
>>> };
>>>
>>> [ Constructor (DOMString type, MediaStreamEventInit eventInitDict)]
>>> interface MediaStreamEvent : Event {
>>>     readonly    attribute MediaStream? stream;
>>> };
>>
>> In this case, I think the question mark should be removed. A
>> MediaStreamEvent without a stream is meaningless.
>
> Agree, provided the prose commands the UA to throw on missing input, or
> we change the constructor as I suggest above.
>
>>> ==============
>>>
>>> dictionary RTCSessionDescriptionInit {
>>>     RTCSdpType type;
>>>     DOMString  sdp;
>>> };
>>>
>>> [ Constructor (optional RTCSessionDescriptionInit descriptionInitDict)]
>>> interface RTCSessionDescription {
>>>                 attribute RTCSdpType? type;
>>>                 attribute DOMString?  sdp;
>>>     serializer = {attribute};
>>> };
>>
>> In this case, I think the question mark for "type" is again
>> meaningless. We've discussed whether "sdp" should be allowed to be
>> empty (for "rollback", for instance), but I don't see a reason to
>> allow it to be missing. Two ways of specifying "nothing here" is one
>> too many. I suggest we remove the question marks.
>
> Agree, provided either:
>
>  1. the prose commands the UA to throw on missing inputs, or
>  2. the webidl provides default values, or
>  3. we change the constructor to: [ Constructor (RTCSdpType type,
>     DOMString sdp)]
>
>
> (on sdp in #3: Two ways of specifying "nothing here" is *two* too many,
> since they can specify "" explicitly for rollback, since it's such a
> rare overload)
>
>
> I prefer 3.

Me too.

>
>>> ==============
>>>
>>> dictionary RTCIceCandidateInit {
>>>     DOMString      candidate;
>>>     DOMString      sdpMid;
>>>     unsigned short sdpMLineIndex;
>>> };
>>>
>>> [ Constructor (optional RTCIceCandidateInit candidateInitDict)]
>>> interface RTCIceCandidate {
>>>                 attribute DOMString?      candidate;
>>>                 attribute DOMString?      sdpMid;
>>>                 attribute unsigned short? sdpMLineIndex;
>>>     serializer = {attribute};
>>> };
>>>
>>
>> We can remove the question mark on "candidate" if the candidate itself
>> is supposed to be NULL in the RTCPeerConnectionIceEvent event, but
>> then we need to add it back in the definition of
>> RTCPeerConnectionIceEvent (currently section 4.8.2). At the moment, an
>> RTCPeerConnectionIceEvent cannot have a null candidate.
>
> Makes sense to me.
>
>> The sdpMid and sdpMLineIndex need question marks, because it's
>> supposed to be legal to specify only one of them.
>
> Agree. How about:
>
> [ Constructor (DOMString candidate, (DOMString or unsigned short)
> sdpMidOrMLineIndex)]
> interface RTCIceCandidate {
>                  attribute DOMString      candidate;
>                  attribute DOMString?      sdpMid;
>                  attribute unsigned short? sdpMLineIndex;
>
> ?

Very nice. Only one will get initialized at object creation, but methods 
using this object as input still needs to check that only one is set 
since the attributes are writable post object creation. We have a 
use-case for not making them readonly right?

> In hindsight, I'm not sure the dictionaries-as-args pattern is useful
> until the interface has at least one optional attribute that has to be
> initialized at construction time.

I agree. It's nice to not have to provide a huge set of dummy values 
because you want to set the n'th optional argument, but we don't have 
many optional ones here.

People that have expressed an opinion seem to agree on what should be 
nullable or not. I think Jan-Ivar's proposals for constructor signature 
changes makes sense as well.

/Adam

Received on Monday, 16 December 2013 07:59:53 UTC