Re: WebIDL extension proposal for [Enumerable] interface attribute

Hi Cameron,

2009/7/2 Cameron McCormack <cam@mcc.id.au>:
> Anselm R Garbe:
>> For example, we are using a Map-like object that exposes file metadata
>> which differs among different files (eg an MP3 file has totally
>> different metadata than an executable), but the metadata might also
>> contain commonly used attributes like the file size or creation date.
>> Our current approach to this problem is to declare
>>
>> typedef Object Map;
>>
>> and using the Map type for these occasions with an informal
>> documentation of the actual Map attributes and their values. However,
>> we'd like to achieve a more formal way to do so.
>>
>> That's why we propose the introduction of an extended interface
>> attribute called [Enumerable] into WebIDL and the introduction of the
>> extended attribute [Optional] for interface attributes. Given the
>> example of file metadata, such a map could be specified as follows:
>>
>> [Enumerable] interface FileMetadata {
>>   [Optional] attribute long size;
>>   [Optional] attribute Date creation;
>>   [Optional] attribute Date modification;
>> };
>>
>> A generic Map-like interface that has no defined optional attributes
>> could look like:
>>
>> [Enumerable] interface Map {};
>>
>> What is your point of view?
>
> I think you should define this instead using named properties.  It
> doesn’t seem to be useful to define an interface that has attributes
> with particular names and types if they might not exist at all (or might
> exist but be different types).

I think it's not a strong requirement of having an optional property
that appears with a different type, it's more a consequence of an
optional property  being possible.

(OT: Btw. why is WebIDL using the attribute keyword instead of the
property keyword if the terminology calls it property?)

>  http://dev.w3.org/2006/webapi/WebIDL/#idl-named-properties
>
> Using the new syntax, I would write:
>
>  interface FileMetadata {
>    omittable getter any getProperty(in DOMString propertyName);
>    omittable setter void setProperty(in DOMString propertyName,
>                                      in any value);
>  };
>
> And then, assuming you already define a set of <key,value> pairs
> associated with a FileMetadata object that represents the file’s
> metadata:
>
>  The supported property names of a FileMetadata object are the keys
>  in the set of <key,value> pairs for that object.
>
> And define what the getProperty() and setProperty() operations do:
>
>  When the getProperty(propertyName) operation is called, it must return
>  the the value of the <key,value> pair for the object where the key is
>  /propertyName/, or null if there is no such pair.
>
> Since it is declared to be omittable, there is no property "getProperty"
> or "setProperty" in a FileMetadata object’s prototype chain.  They are
> invoked only using [[Get]] and [[Put]] on the object.  So:
>
>  var m = getFileMetadata();
>  m.abc;        // Like calling getProperty("abc").
>  m.def = 123;  // Like calling setProperty("def", 123).
>  m.toString;   // This gets the value of the "toString" property from
>                // the Object.prototype object.

Well, we used a similar approach so far, but honestly it looks very
complex and implicit to me. Especially the aspect that it may result
in different behavior among different language bindings, such as the
Java binding (see below).

The main idea behind the optional properties is that it allows to
*formally* define "usual" properties, that are expected to be
supported by an implementation, but must not. So it's a MAY, not a
MUST spec-wise. Your proposed approach isn't really better than our
current approach of having typedef Object Map, and using that Map type
for what we are after, because the "usual" properties supported can't
be specified in a formal way (they are specified in a comment block
instead). Also, as you stated, your approach doesn't allow
enumerations of such optional properties, which is our main
requirement.

> In another language binding that doesn’t support object indexing like
> this, the operations would correspond to methods, e.g. in Java the
> interface would be:
>
>  interface FileMetadata {
>    Object getProperty(String propertyName);
>    void setProperty(String propertyName, Object value);
>  }

I understand that you are concerned with the Java language binding
here since it doesn't support non-final properties in Java interfaces.
However such a Map-like interface would perfectly map to Java's
Hashtable class for instance, given that some extended interface
attribute like [Enumerable] would exist. The conversion is up to the
language binding implementation anyways, so that would be easily able
to synchronize between Hashtable and the specified WebIDL interface in
the case of a Java binding (even if there are non-optional
attributes). The same applies to most other languages that support
associative arrays in general.

> If you have properties that aren’t optional, then you can define them as
> attributes on the interface:
>
>  interface FileMetadata {
>    attribute DOMString filename;
>
>    omittable getter any getProperty(in DOMString propertyName);
>    omittable setter void setProperty(in DOMString propertyName,
>                                      in any value);
>  };
>
> and when you do m.filename, it will get that attribute’s value rather
> than invoke the getter operation.

Ok, I assumed that non-optional properties would still be possible.

> What this doesn’t get you, and which maybe I’ll add some Web IDL support
> for, is allowing named properties to have different types.  The host
> object [[Put]] method
>
>  http://dev.w3.org/2006/webapi/WebIDL/#put

Well as said, we could live without this particular requirement,
though if properties are declared as optional, it won't be impossible.
I see the dilemma here...

> doesn’t deal with converting the ECMAScript value to an IDL value, but
> it should convert the assigned ECMAScript value to the IDL type of the
> setter operation’s second argument.  Maybe I should allow specs to hook
> in to say what type to convert the assigned ECMAScript value to, e.g.
> just with prose:
>
>  The type of the FileMetadata named property "size" is long.
>
> That then would invoke the “convert ECMAScript value to an IDL long”
> algorithm from the host object [[Put]] method.
>
>
> The other thing it doesn’t get you is enumerability of the properties.
> Currently any corresponding named properties (i.e., properties that
> exist on the host object that correspond to a supported named property)
> are DontEnum.  I can add an extended attribute, say
> [NamedPropertiesEnumerable], for this.

That wouldn't go far enough, because it would only enumerate the named
properties and for them it's rather pointless to be enumerable,
because they are known anyways due to their declaration in the WebIDL.
The enumeration is especially a requirement for those properties that
aren't declared.

Kind regards,
Anselm

Received on Thursday, 2 July 2009 08:51:21 UTC