W3C home > Mailing lists > Public > public-script-coord@w3.org > July to September 2011

Re: WebIDL editorial feedback

From: Cameron McCormack <cam@mcc.id.au>
Date: Fri, 19 Aug 2011 12:43:27 +1200
Message-ID: <4E4DB1AF.1050903@mcc.id.au>
To: timeless <timeless@gmail.com>
CC: public-script-coord@w3.org
Thanks for the detailed editorial feedback, timeless.  In my response 
below, any comment I've snipped is one that I agree with and have 
addressed as requested.  There are a couple of questions in there, so 
please take a look.

If you are satisifed with the response, could you please indicate so for 
the Disposition of Comments document.



[part 1]

On 9/07/11 8:54 AM, timeless wrote:
 >> Let definition be the definition whose qualified name is equal to
 >> the concatenation of name, two U+003A COLON (":") characters and
 >> the scoped name, then the scoped name resolves to that definition;
 >> end these steps.
 > I found this statement to be strange, there's no "if", and no
 > obvious sign of what is being verified to decide whether to break.
 > I'm sure we all understand what the goal of the text is, but could
 > the prose be clarified?

Something went wrong editing that sentence.  I've replaced it with:

   If there is a definition whose qualified name is equal to the
   concatenation of name, two U+003A COLON (":") characters and the
   scoped name, then the scoped name resolves to that definition;
   end these steps.

 >>     // Exception field identifier: "code"
 >>     long code;
 > If something like this doesn't have a qualified name, then a comment
 > explaining it would be beneficial

I added a note after the IDL block:

   Also note that the exception fields, operations and attributes above
   do not have qualified names, simply because there is no need to be
   able to reference them from other scopes.

 >> If the definition is declared at the outermost scope, then the
 >> qualified name of the definition is two consecutive U+003A COLON
 >> (":") characters followed by the identifier of the definition.
 >> If the module has a [Prefix] extended attribute whose argument starts
 >> with the string “::”, then the prefixed name of the module is a
 >> scoped name constructed by concatenating the [Prefix] argument, the
 >> string “::” and the module’s identifier.
 > It seems like you'd be better served by defining a token to mean this
 > than using two different ways of expressing this content in the spec.

This is about using

   two consecutive U+003A COLON (":") characters


   the string “::”

to mean the same thing?  Yeah, that's a good point.  I introduced a term
"double colon" to refer to this.

 >> Otherwise, if the module has a [Prefix] extended attribute whose
 >> argument does not start with the string “::”, then the prefixed
 >> name of the module is a scoped name constructed by concatenating
 >> the prefixed name of the module’s enclosing module (or “::”
 >> if there is no enclosing module), the string “::”, the [Prefix]
 >> argument, the string “::” and the module’s identifier.
 > I'm pretty sure this allows me to generate ::::foo::bar when there is
 > "no enclosing module", which seems wrong.

Yeah.  Fixed that, and a small problem in the final bullet of that list.

 >> module gfx {
 >> -blank line-
 >>   module geom {
 >>     interface Shape { /* ... */ }; -not-a-blank-line-
 >>     interface Rectangle : Shape { /* ... */ };
 >>     interface Path : Shape { /* ... */ };
 >>   }; -not-a-blank-line
 >> -blank-line
 >>   interface GraphicsContext {
 >>     void fillShape(in geom::Shape s);
 >>     void strokeShape(in geom::Shape s);
 >>   }; -not-a-blank-line-
 >> }; -not-a-blank-line-
 > I found the lack of a blank line before the lines i tagged as
 > "-not-a-blank-line-" made it hard to read the content, as I was
 > expecting a consistent and balanced whitespace style and this isn't.
 > (This also applies to the last line in module gui {...};)

So my rules there are:

   * If the container has only single line declarations inside it,
     don't put any blank lines inside the container.
   * Otherwise, if it has any declarations that take more than one
     line, put a blank line before each one.

I tried both adding and removing blank lines, but I wasn't happy with
either, so I left it as is.

 >> An interface is a definition (matching Interface) that defines an
 >> interface that objects in the system can implement.
 > "the system" seems odd.

Would s/the system/a conforming implementation/ work?

 > The WebIDL spec used to imply null as a valid case, that changed.
 > Otherwise your mutually referential example is mostly unsolvable and
 > thus incredibly painful. Alternatively you could probably provide for
 > some other solution or a different example...

I did "Dog?" and "Human?".

 >> [25] Get → InheritsGetter
 >>   | GetRaises
 >>   | ε
 >> [26] InheritsGetter  → "inherits" "getter"
 >> [27] GetRaises → "getraises" ExceptionList
 >> [28] SetRaises → "setraises" ExceptionList
 >>   | ε
 > Is there a reason the ε is in Get instead of in GetRaises (to match 

No, I'll move it down to GetRaises for symmetry.

 >> [39] Argument  → ExtendedAttributeList In Optional Type Ellipsis 
 > It would be vaguely nice if if the syntax was described like this:
 > [x] ArgumentList  → Argument Arguments VaradicArgument
 >   | ε
 > [x] Arguments → "," Argument Arguments
 >   | ε
 > [x] Argument  → ExtendedAttributeList In Optional Type identifier
 > [x] VaradicArgument → ExtendedAttributeList In Optional Type "..." 
 >   | ε
 > (you could retain the "Ellipsis" token if you liked, but in that case
 > you should get rid of the | ε bit...)

I think it would need to be more complicated than that because you need
a comma before the variadic argument if it is not the only argument, or
to omit it if it is.  I'm going to leave the grammar a bit lax here and
rely on the prose to disallow "..." in the middle of an argument list to
avoid complicating it.

 >> A given special keyword MUST NOT appear twice on an operation.
 > I don't understand the need for this. Doesn't the grammar prevent it
 > automatically?

No it doesn't.  Since it allows the special keywords in any order, you'd
get an explosion of productions in the grammar if it were to.

 >> Special operations declared using operations MUST NOT be variadic nor
 >> have any optional arguments.
 > If you use the grammar I suggest above, you could probably adjust
 > other parts of the grammar to distinguish between ArgumentList and
 > PossiblyVaradicArgumentList....

Not going with the grammar suggestion above, so I will leave this.

 >> An ECMAScript implementation of the IDL would behave as follows:
 >> ECMAScript
 >> var s = new Student();
 > s/implementation of the/consumption of an object defined by that/ ? -
 > not a fan of consumption, please feel free to pick something else...

I think "implementation of the IDL" is consistent with the wording I use
in the conformance classes defined at the top of the document, so I will
leave this one.

[part 2]

 >> Named properties
 > The section is called "Named properties", but many of the actual
 > things uses "name <foo>" instead of "named <foo>".
 > I personally think of "foo[bar]" as a "named getter", because it's a
 > getter that gets things for a named property, it does not "get the
 > name of a thing".

I agree the terms "name getter" and "index getter" aren't the best, and
that "name getter" does sound like it is getting a name, rather than
getting the value of a property by name.

I don't think "named getter" is better, because that sounds like it is
the getter itself that is named.

I'm going to rename them to "named property getter" and "indexed
property getter".  It's a bit more verbose, but it's a more accurate

 >> If an interface supports named properties, then the interface
 >> definition MUST be accompanied by a description of what the ordered
 >> set of names the object can be indexed with at any given time is.

 > s/what//; s/the object can be indexed with/that can index the object/;
 > s/time is/time/;

Instead I did

   If an interface supports named properties, then the interface
   definition MUST be accompanied by a description of the ordered set of
   names that can be used to index the object at any given time.

 >> Name getters and deleters MUST be declared to take a single 
DOMString argument.
 > s/Name/Named/ ?

Used "named property getters" per above.

 > I can't tell from the prose that only <name creator> and not <name
 > setter> is executed when doing a first assignment to foo[bar] for a
 > "bar" not_in foo.

I added this paragraph to the #idl-special-operations section:

   Some language bindings, such as ECMAScript, do not distinguish
   assignment to an existing indexed or named property and the creation
   of a new one. Regardless, it is the creator that is invoked when an
   attempt is made to create a new indexed or named property, and the
   setter when the property already exists.

 >> A static operation is one that is not called on a particular 
instance of the
 >> interface on which it is declared, and is instead associated with 
the interface
 >> itself.

 > In Java, it's possible to do: ObjectInstance.staticFunction(args),
 > which is equivalent to Class.staticFunction(args). The prose above
 > did not help another reader determine whether this was allowed here.
 > In JavaScript, statics are only available from the Class and not the
 > ObjectInstance.

It's language binding specific.  I will point that out with this

   It is language binding specific whether it is possible to invoke
   a static operation through a reference to an instance of the

 >> If the identifier of the dictionary is followed by a colon and
 >> a scoped name, then that scoped name identifies the inherited
 >> dictionary. The scoped name MUST resolve to a different dictionary.
 >> The inherited dictionaries of a given dictionary D is the set of all
 >> dictionaries that D inherits from, directly or indirectly.

 > There doesn't seem to be any propose here to prevent loops (there is
 > in other sections).

Added a paragraph similar to the one in the interfaces section.

 >> [11]  DictionaryMembers → ExtendedAttributeList DictionaryMember
 >>           DictionaryMembers
 >>         | ε
 >> [12]  DictionaryMember → Type identifier DefaultValue ";"

 > Is there a reason ExtendedAttributeList is in DictionaryMembers
 > instead of in DictionaryMember?

It's consistent with the productions for attributes, constants, etc.

 >> No extended attributes are applicable to exception fields.
 >> [15]  ExceptionMembers → ExtendedAttributeList ExceptionMember
 >>           ExceptionMembers

 > I think that you probably want to omit ExtendedAttributeList here, as
 > the prose forbids it...

I want to allow it so that people can use their own extended attributes
there if they want.

 >> An exception can be defined to inherit from another exception. If
 >> the identifier of the exception is followed by a U+003A COLON (":")
 >> character and a scoped name, then that scoped name identifies the
 >> inherited exception. The scoped name MUST resolve to a different
 >> exception.

 > There doesn't seem to be any propose here to prevent loops (there is
 > in other sections).

Fixed as above.

 >> Each exception field (matching ExceptionField) is specified as a type
 >> (matching Type) followed by an identifier (given by an identifier
 >> token following the type). If the Type is a scoped name, then it MUST
 >> resolve to an interface or typedef.

 > Is there a reason 'interface' isn't linked? `resolve` is linked two 
 > earlier and again here.

I had a rule I was (mostly) following, which was to link it the first
time it appears in a sequence of consecutive paragraphs.  Any other
block such as an <ol>, a note, and IDL block etc. would reset that.

I probably didn't apply the rule consistently enough.  I'll think about
linking each instance of the word, but I won't do that right now.

 >> In an ECMAScript implementation, the different types of DOMExceptions
 >> could be distinguished in a number of different ways:
 >> ECMAScript
 >> } catch (e) {
 >>  // By testing with "instanceof".
 >>  if (e instanceof HierarchyRequestError) {

 > It would be good if you recommended that authors *never* use this
 > method.
 > Some prose is probably valuable here:
 > "Note that using `instanceof <Exception>` can return `false` if the
 > exception object comes from a different document than the global scope
 > of the running script even if the exception is an instance of the an
 > <Exception> class of the given name in its own document." -- Someone
 > else can probably provide an improved block for this, and see thread
 > [2] for comments about this hazard.

That text sounds good.  I added it with slight tweaks, and removed the
example of using instanceof in the code block.

 >> The type being given a new name is specified after the typedef
 >> keyword (matching Type), and the identifier token following the type
 >> gives the name. The Type MUST NOT be a scoped name that resolves to
 >> an interface.

 > I think one of 'Type' or "NOT" here is wrong, I was reading:
 >> [16]  Typedef → "typedef" Type identifier ";"
 > And assumed the 'NOT' was applying to 'Type', the prose probably
 > wants: s/Type/type/ -- to mean 'The type [being given the new name
 > `identifier`] MUST NOT ...', or s/Type/identifier/.

No, I think it's correct as is.  I wanted to prevent typedefs from being
used to give new names to existing interfaces, just for simplicity.  I
should extend that to dictionaries, too.

 >> 3.8. Objects implementing interfaces
 >> There is no way for a user object to represent an exception.

 > ?

I want to state that in systems implementing some IDL, you can't use
user code to implement the exception "class".  I'm open to suggested
wording there.

OTOH, you're not allowed to use an exception as a type for attributes,
operation arguments, etc. anyway, so it probably doesn't matter.

 >> Only interfaces with the following characteristics can be implemented
 >> as user objects:

 > I found this list hard to parse, based on later prose, I think this 
should be
 > changed:
 > s/with/with all of/

Makes sense.

 > Some additional prose might be warranted to remind readers that
 > <Dictionaries> are also allowed....

This section is only intended to restrict what kinds of interfaces user
objects can implement, not any other kinds of constructs like
dictionaries.  There's also no distinction between user objects and
platform objects for dictionaries.

At the IDL level, dictionaries aren't even objects -- they're just
an abstract data type.  I think it's fine not to mention them here.

 > Also note that "only...can" isn't an RFC word construct. It might be
 > better to say something like "User objects SHOULD NOT be treated as an
 > interface unless all of the following apply".

I use wording like "can" and "cannot" when it is just describing the
consequences of other RFC2119 requirements in the document.

 > Afaict, this isn't forbidden or at least actively discouraged:
 > interface Foo {};
 > Foo implements Bar;
 > Foo implements Baz;
 > interface Bar { attribute short x; attribute short y; };
 > interface Baz { attribute short x; attribute short z; };
 > There is text in a couple of other sections which talks about things
 > being undefined or needing to be clarified by prose, but there
 > definitely isn't any near the <implements> section.

Yeah, fair enough.  I should just disallow this.  I've added the
following to the #idl-implements-statements section:

   Implements statements MUST NOT be used such that the identifier of any
   member of one interface’s consequential interfaces is the same as
   the identifier of one of the interface’s own members.

and removed the talk of this case being undefined in

 >> then the object will not be considered to be one that implements that
 >> interface.

 > s/will not/should not/

Not using RFC2119 terminology here because this is just a general
statement of what the language bindings require.

 >> all conversions necessary will be performed before the operation is 
 >> or the attribute updated.

 > s/will/should/ (RFC word)

Again, this is a consequence of MUSTs in the later sections describing
the properties that exist for attributes and operations.

 > s/updated/is updated/

It's valid English, but I'll put the "is" in there explicitly for
symmetry with the following sentence.

 >> In some language bindings, type conversions could result in an
 >> exception being thrown.

 > s/could/may/ ?

I don't think MAY is right, here.

 >> In such cases, these exceptions will be propagated to the code that
 >> made the attempt to invoke the operation or assign to the attribute.

 > s/will/should/ ?

This is also informative text that describes normative requirements
later on.

 >> [60]  TypeSuffixStartingWithArray → "[" "]" TypeSuffix
 >>         | ε

 > I'm trying to understand the reason that TypeSuffixStartingWithArray
 > exists in WebIDL. It seems like its goal is to cause <AttributeType>
 > for "any" to not be nullable but to allow for arrays whose row and
 > subs can be nulled.

It exists because I want to disallow `Type??` but allow `Type?[]?[]?`
etc. and also yes to disallow `any?` but allow `any[]`.

 >> Note also that null is not a value of type DOMString. To allow null,
 >> a nullable DOMString, written as DOMString? in IDL, can be used.

 > I know it's a note, but it feels like "must" or "should" would be
 > appropriate instead of "can". You're trying to say "needs to be
 > used"....

I will use "needs to be used".

 >> Authors of specifications using Web IDL might want to obtain a sequence
 >> of Unicode characters given a particular sequence of 16 bit unsigned
 >> integer code units, however.

 > The "however" here feels dangling.

Moved it to the front of the sentence.

 >> There is no way to represent a sequence constant value in IDL.
 >> There is no way to represent an array constant value in IDL.
 >> There is no way to represent a Date constant value in IDL.

 > Should these be "constant <foo> value"?

That sounds slightly better.

 >> It may be that [Callback] is not the best name for the extended
 >> attribute anyway, although it does capture many uses of interfaces
 >> that user objects can implement.

 > "UserObject" ?

I will consider that.  I haven't made the change right now though.

 >> Example
 >> The following IDL fragment defines simplified versions of a few DOM
 >> interfaces, one of which is annotated with the [Callback] extended
 >> attribute.

 > Please provide an example of [Callback(identifier)]. The prose is
 > insufficient for this.

There is an example in the #es-Callback section.  I will reword the
sentence that links to it to state that it's got an example there too.

 >> Each ECMAScript global environment ([ECMA-262], section 10.2.3) MUST
 >> have its own unique set of each of the initial objects, created
 >> before control enters any ECMAScript execution context,

 > s/any/a related/

I'll do s/any/any ECMAScript execution context associated with the
environment/ and s/global environment is created/environment is

 >> but after the global object for that global environment is created.
 >> The [[Prototype]]s of all initial objects MUST come from
 > s/MUST/in a given global environment MUST/

 >> the same global environment.

 > You *might* want s/the/that/, it's a stronger restriction than the
 > current text -- currently a bunch of objects can all have prototypes
 > which come from one *other* global environment (I've actually had code
 > which did things like this, but no one in their right mind would want
 > it -- thus my suggestion of s/the/that/).

Yeah, I think that's a good change.

 >> If the value is an object reference to a special object that represents
 >> an ECMAScript undefined value, then it is converted to the ECMAScript
 >> undefined value. Otherwise, the rules for converting the specific type
 >> of the IDL value are performed.

 > <the rules for converting the specific type of the IDL value> doesn't
 > seem to specify something, is it a certain section? Is it the
 > following list? ...

It is the following list.  I tried to make this clearer by saying in
#idl-any that any values remember what paricular IDL type they are, and
then here in this section I now say:

   Otherwise, the rules for converting the _particular type_ of the IDL
   any value as described in the remainder of this section are performed.

 >> ECMAScript functions that implement an operation whose IDL specifies a
 >> void return type MAY return any value, which will be discarded.

 > should `will` be SHOULD/MUST?

Actually, I will make this say

   ECMAScript functions on user objects that implement an operation whose
   IDL specifies a void return type MAY return any value, which will be

I still use "will" because the actual requirement for discarding it is
done in the section later that talks about invoking operations on user
objects implemented in JS.

 >> Set x to x modulo 28.

 > Is modulo specifically meant to be an ECMAScript operation? If so,
 > was there something that indicidated that (if so, I missed it), if
 > not, I think you probably need to specify whose modulo you're using
 > (specifically relating to how negative numbers are handled).

Good point, although the algorithm does ensure that the number is
positive first.  At the top of #ecmascript-binding it does say that the
conventions of ES-262 section 5.2 are used, and that section defines
modulo.  I'll point out more explicitly that the mathematical operations
from that section are used here.

[part 3]

 >> An IDL sequence value S0..n−1 of type sequence<T> is converted to an
 >> ECMAScript Array object as follows:
 >> 1.    Let A be a new Array object created as if by the expression [].
 > It would be somewhat nice if the array size could be set here instead
 > of relying on 3.3 to increase the size. I'm not sure if this is
 > something which is detectable...

I don't think this is detectable.  I also don't think it matters if the
length increases with each [[Put]], so I'm going to leave this one.

 >> whenever an Array is passed to drawPolygon a reference to it will 
never be kept.
 > s/never/not/ -- or "no reference to it will be kept after the call 

Went with the latter.

 >> // "hi" will be alerted before drawPolygon() returns.
 > technically it will be alerted before drawPolygon() is called, right?

Both are true. :-)

 >> canvas.drawPolygon
 >>  ([false, '',
 >>    { valueOf: function() { alert('hi'); return 100 } }, 0,
 > I know the trailing semicolon is optional, but could I get you to
 > include it? :) --
 > also applies to 'throw "abc" later.

Sure.  (My personal style is usually to omit semicolons in case of a
single return statement.)

 >>    '50', new Number(62.5)]);
 >> // Modifying an Array that was passed to drawPolygon() is guaranteed 
not to
 >> // have an effect on the Canvas, since the Array is effectively 
passed by value.
 >> a[0] = 20;
 > This is a bad example, because afaiu, drawPolygon() is an
 > instantaneous function. A better example would be a [CallBack]
 > interface with a sample JS impl which stashes its value and returns it
 > so you can confirm that it isn't change.

I don't quite follow your example.  I changed the existing example a
bit, maybe you can take a look.

 >> The value of the internal [[Prototype]] property of an platform array
 >> object MUST be the Array prototype object ([ECMA-262], section 15.4.4).
 > This doesn't specify which global scope, I hope that's properly implied.

I think it wasn't.  I've pointed out now that platform array objects are
platform objects, and thus are associated with a particular global

 >> Platform array objects defy being fixed;
 > This is a strange construct. I understand it, but I think you might
 > want to rephrase it.

I kind of liked how it sounded like the objects were resisting. :)  I
did s/defy being/cannot be/.

 >> if Object.freeze, Object.seal or Object.preventExtensions is called 
on one,
 > s/if/if any one of/ ?

Don't think that's necessary.

 >> the function MUST throw a TypeError.
 > function a() { b() } function b() { throw 1; } -- is a() said to throw
 > 1? I worry that your must throw overspecifies who should do the
 > throwing instead of ensuring that it be thrown.

I think it'll be indistinguishable whether the function itself or one it
delegates to throws the TypeError.  It's probably not worth worrying

 >> An ECMAScript value V is converted to an IDL array value of type T[] 
as follows:
 > ..
 >> 1.    Initialize n to be the result of calling [[Get]] on V with 
property name
 > “length”.
 >> 2.    Set n to ToUint32(n).
 >> 3.    Initialize E0..n to be a list of IDL values.
 > It feels like 'E' comes out of nowhere, I need to check your other
 > bits to see if this is standard.

Do you mean the choice of the variable name /E/ or the convention of
writing E_0..n?  I think I'll rename it to /values/, anyway.

I should have stronger conventions around variable name choices and
capitalisation, but I haven't got around to sorting that out.

 > ..
 >> 6. The IDL array value is a fixed length array of length n whose 
values are E0..n.
 > s/n/n-1/g ?


 >> var a = [4, 8, 15, 16, 23, 42];      // Numbers can be assigned into 
the array.
 >> for (var i = 0; i < 6; i++) {
 >>  results.numbers[i] = a[i];
 >> }
 >> results.numbers = a;                 // This has no effect, since 
numbers is
 >>                                      // read only.
 > This should be done before the for loop above, otherwise it's
 > impossible to determine that it has no effect.

I think it's fine -- the effect I'm more interested in demonstrating is
that changing a afterwards does not affect the IDL array.

 >> interface LotteryResults {
 >>   attribute unsigned short[] numbers;
 >> };
 >> then an Array object can be assigned to the numbers property.
 >> Unless the prose accompanying the interface said otherwise,
 >> this would result in a fixed length array of whatever length
 >> the Array has being assigned to the IDL attribute.
 >> ECMAScript
 >> var results = new LotteryResults();
 >> results.numbers.length;       // Evaluates to 6.
 > It would be helpful if you had a results.numbers.push() here showing
 > that it didn't do anything.

I've added that at the end of the example.

 >>                               // that represents the fixed length 
IDL array,
 >>                               // not the Array object assigned in 
the previous
 >>                               // statement.
 > A `results.numbers != a` statement might be useful if that's the case.


 >> Platform objects returning an ECMAScript Date object from attributes,
 >> operations or exception field do not hold on to a reference to the 
Date object.
 > s/on to/onto/

I think it's fine as is.

 >> Script that modifies a Date object so returned cannot affect the
 > s/returned/retrieved/
 > s/Script/A script/

I think of script as a mass noun too, but OK.

 >> When the [AllowAny] extended attribute is present on the argument,
 >> that disqualification is not performed.
 > s/performed/applied/ ?

I think "performed" is fine.

 >> If the [OverrideBuiltins] extended attribute appears on an interface,
 >> it indicates that for a platform object implementing the interface,
 >> properties will appear to be own the object
 > s/own/on/ (or is it 'owned by'? -- hard to tell)

I did mean "on".

 >> corresponding to all of the object’s supported property names,
 > this is awkward/misordered. <all properties corresponding to the
 > object's supported property names will appear to be on the object
 > itself> ?

Yes, that's better.

 >> properties to be exposed only if there is no property with the
 >> same name on the object itself or somewhere on its prototype chain.
 >> The [OverrideBuiltins] extended attribute MUST take no argument
 >> and MUST NOT appear on an interface that does not define a name
 >> getter or that also is declared with the [ReplaceableNamedProperties]
 >> extended attribute.
 > An example with [ReplaceableNamedProperties] would be useful.

There is one in the #ReplaceableNamedProperties section.

 >> If the [Replaceable] extended attribute appears on a read only
 >> attribute, it indicates that setting the corresponding property
 >> on the platform object will result in that property being
 >> reconfigured to one that is unrelated to the attribute, and
 >> which has the value being assigned.
 > What happens if i delete a replacement for a replaceable property? I
 > believe the original property is exposed. The text should make this
 > clear.

I think this text is misleading, anyway.  Now that IDL attributes
correspond to accessor properties on the interface prototype object,
[Replaceable] doesn't mean that the object's own property is
reconfigured -- there is no such property.  Instead it means that the
accessor has a setter that creates an own property to shadow itself.
Then if you delete the own property the accessor will shine through

So I replaced that paragraph with:

   If the [Replaceable] extended attribute appears on a read only
   attribute, it indicates that setting the corresponding property on the
   platform object will result in an own property with the same name
   being created on the object which has the value being assigned.  This
   property will shadow the accessor property corresponding to the
   attribute, which exists on the interface prototype object.

 >> Assigning to the value property on a platform object implementing
 >> Counter will sever the link between the property and the IDL
 >> attribute it initially corresponds to:
 > s/sever/disconnect|disable/ - severing is generally considered permanent.

I reworded the example in line with the above change, too.

 > Also, it'd be good to include an delete undoing this in the example.


[part 4]

 >> 4.3.13. [TreatNullAs]
 >> If the [TreatNullAs] extended attribute appears on an attribute or
 >> operation argument whose type is DOMString,...
 > I know it isn't mentioned as allowed (and is generally forbidden by
 > the last line before the example), but perhaps specific text should be
 > considered for:
 > [TreatNullAs=EmptyString] attribute DOMString? confused;

I added a note explicitly stating that [TreatNullAs] on a "DOMString?"
type is disallowed.

 > You aren't using .owner in your example, I'm pretty sure you want to,
 > and that it will (once the earlier idl change is made) get a comment
 > that 'This assigns the string "" to the .owner property

Yes, did so.

 >> 4.3.14. [TreatUndefinedAs]
 >> The [TreatUndefinedAs] extended attribute MUST take an identifier:
 >> either EmptyString or Null.
 > Can I have:
 > [TreatUndefinedAs=Null,TreatNullAs=EmptyString] attribute DOMString? 
 > and is its processing model different than:
 > [TreatNullAs=EmptyString,TreatUndefinedAs=Null] attribute DOMString? 

No, since [TreatNullAs] cannot be put in a "DOMString?" type.

 >> The following IDL fragment defines an interface that has one 
attribute with
 >> the [TreatUndefinedAs] extended attribute,
 > The same comments for Dog apply to Cat...


 >> 4.3.15. [Unforgeable]
 >> If the [Unforgeable] extended attribute appears on a read only 
 >> it indicates that the attribute will be reflected as an ECMAScript 
 >> in a way that means its behavior cannot be modified and that 
performing a
 >> property lookup on the object will always result in the attribute’s 
 >> value being returned.
 > This doesn't say that a forging getter isn't fired first before
 > returning the unforged value.

I'm not sure what you mean.

 >> The [Unforgeable] extended attribute MUST NOT appear on anything other
 >> than a read only attribute.
 > While this is obvious, an example of an invalid instance of this would be
 > appreciated.

I've not tended to include examples of invalid IDL, but anyway I don't
think it's necessary here for understanding.

 >> It also MUST NOT appear on an attribute on interface A if there exists
 >> another interface B that defines any interface member with the same 
 > An example of this would be easy to provide.

Here would be OK, though, since it's a bit more complicated.

Actually I am going to further restrict where [Unforgeable] is allowed;
please take a look at the updated text.

 >> or which is a consequential interface of A.
 > I suspect this would be easier for me to puzzle out, but since I'm
 > already asking for examples, one for this would be appreciated. And
 > yes, I know that someone has to make a test case for each testable
 > assertion, on the bright side, by doing this, you're making their life
 > easier :).

It's simpler now.

I removed the consequential interface part of the restriction because of
the changes mentioned earlier in this email about disallowing mixing in
interfaces if they have members with clashing names.

 >> An ECMAScript implementation of the interface will expose the username
 > I'm not sure if this is supposed to be `ECMAScript implementation of
 > the interface` or just An ECMAScript implementation of WebIDL for an
 > object implementing this interface ...
 > To me, the current text implies that if I write:
 > function MySystem(){}
 > MySystem.prototype....
 > But normally we're talking about Host/System objects and not
 > ECMAScript implemented objects.

I linked to the definition of "conforming ECMAScript implementation" to
make that clearer.

 >> 4.5. Interfaces
 >> The name of the property is the identifier of the interface, and its
 >> value is an object called the interface object, which provides access
 >> to the constants, attributes and operations defined on the interface.
 > This doesn't say how it does this for magic operations.
 >> The property has the attributes { [[Writable]]: true,
 >> [[Enumerable]]: false, [[Configurable]]: true }.
 > I found this statement to be too far from the correct relevant
 > `property` (which was the one for the interface, and not for
 > properties of that interface). I think the simplest solution is to
 > remove the 'which provides access...' bit. It's made clear enough by:
 >> The characteristics of an interface object is described in section 
4.5.1 below.
 > s/is/are/
 >> The characteristics of a named constructor is described in section 
4.5.2 below
 > s/is/are/
 > This is really:
 > s/(The characteristics .*) is (.*)/$1 are $2/g;


 > --in case i forget to tag some other instances...

(There was only one more instance.)

 >> 4.5.1. Interface object
 >> The interface object also has properties that correspond to the
 >> constants and static operations defined on that interface, as
 >> described in sections 4.5.4 and 4.5.6 below.
 > This seemed to conflict with the earlier statement:
 > | which provides access to the constants, attributes and operations
 > | defined on the interface.
 > It's technically correct because some things are on <interface object>
 > and some are on <interface object prototype>, but it's confusing.

Indeed.  The earlier sentence has been removed, and this one here is

 >> This object has properties that correspond to the attributes
 >> and operations defined on the interface, and is described in
 >> more detail in section 4.5.3 below.
 > This doesn't match the style of the previous sections <The
 > characteristics of...>

Meh. :)

 > interface A {}
 > interface B : A {}
 > interface C {
 >   void d(A[] a);
 >   attribute B[] e;
 > }
 > c = new C;
 > c.d(c.e);
 > I don't think that this is handled properly (compare with the next
 > case which tries to handle inheritance).

I see.  I'm not sure it's worth handling this at this point -- if people
can point out cases where this would be useful, I'll allow it.

 >> \-> Any other platform object
 >>     Add to types the object type and an interface type for all
 >> interfaces that are equal to, or inherit from, at least one of
 >> the interfaces that the platform object implements.
 > interface A {};
 > interface B : A {};
 > C implements A;
 > c instanceof C
 > Call step 7-1-2 with `c`, I think that this prose says that 'B' should
 > be added to the list. I don't think that's wanted behavior.

Ah, it should be s/inherit from/are an inherited interface of/.

 >> \-> A native Array object
 >>     (That is, a native object whose [[Class]] is "Array".)
 >> Add to types the object type, an interface type for each
 >> interface annotated with the [Callback] extended attribute
 >> and all array types.
 > This puzzles me, I was wondering about [PlatformObject(),
 > PlatformObject2()].

I don't want the overload resolution algorithm to have to inspect all
the types of the array elements.  So any array type should match.  I see
I missed out sequence types here, so I'll add them too.

 > I'm also unclear as to why [Callback] is being considered here.

I want not to disallow:

   interface A {
     attribute DOMString x;

   var o = [];
   o.x = "abc";

 > Also note that you use 'for all' and 'for each' in 7-1-2
 > inconsistently, I think I expected 'for each' in all cases (although
 > some prose may need to be adjusted to get 'for each' to fit
 > correctly).


 >> 7-1-2-4. If there exists an entry in candidates with type list t
 >> where ti ∈ types, then remove from R all entries with type list
 >> t where ti ∉ types.
 >> 8. Return R.
 > I don't think 'R' is defined in this process, you do have an 'S' from
 > steps 1, 2, and 3, and you also have 'candidates' (from step 2).

Indeed it should be candidates, as Lachy points out too:

 >> If S contains more than one entry, then the constructor call is
 >> ambiguous. Remove all but one entry from S according to rules
 >> specified in the description of interface I, or arbitrarily if
 >> no such rules exist.
 > What do I do when rules exist and they're incomplete/ambiguous? :)

I'm not sure I like the "arbitrarily" in here anyway.  Probably I should
just require that specifications do have rules that correctly resolves
the ambiguity, but I don't have a conformance class for specifications
at the moment. :(

 >> 7. Let x be the extended attribute that represents the constructor
 >> and t0..m−1 be the type list of the single entry in S.
 > You switched to 'm' from 'n', is there a need for this? Shouldn't the
 > resulting list in S actually have the same number of arguments as the
 > input to the algorithm?

n is already used earlier in the algorithm (well, as input to it).  It
shouldn't have the same count, because of cases like

  interface A {
    void f(DOMString x);

  a.f("a", "b");

 >> 8. Let idlarg0..m−1 be a list of IDL values, where idlargi is the
 >> result of converting argi to an IDL value. These conversions
 >> MUST be done in order from arg0 to argm−1.
 > Note that here you're indexing on 0..m-1 for input 0..n-1.

It should be guaranteed that m ≤ n here.

 >> 9. Let R be the result of performing the actions listed in the
 >> description of the constructor represented by x with idlarg0..m−1
 >> as the argument values.
 > This process does define `R`!


 >> If the internal [[Call]] method of the interface object returns
 >> normally, then it MUST return an object that implements interface I.
 > And if it somehow decides to do something stupid? : (obviously, doing)
 > that is a violation of the spec, but violations happen...)

Then it returns it.  I don't think there is a need to constrain this,
since returning a bad value is already bug.

 >> 4.5.4. Constants
 >> For each constant defined on an interface A, there MUST be a
 >> corresponding property on the interface object, if it exists,
 > I expected any text relating to <interface-prototype-object> getting
 > a constant to be here, not later. You can add the special stuff later
 > and still have the general bit for <interface-prototype-object> here

Do you mean you'd rather the order be swapped around to describe them
being on the interface prototype object first, and then on the interface
object?  I used the current order because it's more normal to use
Node.ELEMENT_NODE rather than myNode.ELEMENT_NODE.

 >> if the identifier of the constant is not “prototype”. The property
 >> has the following characteristics:
 >>    The name of the property is the identifier of the constant.
 >>    The value of the property is that which is obtained by converting
 >>      the constant’s IDL value to an ECMAScript value.
 >>    The property has attributes { [[Writable]]: false, [[Enumerable]]:
 >>      true, [[Configurable]]: false }.
 >> In addition, a property with the same characteristics MUST exist
 >> on the interface prototype object, unless:
 >>     the identifier of the constant is “constructor”; or
 >>     the identifier of the constant is “toString” and the interface
 >>       has a stringifier.
 > Questions that came up:
 > [Constructor()] interface B { const short _constructor = 6; }
 > other than being mostly stupid, that more or less does something?
 > b=new B; b.constructor===6, b.prototype.constructor===B ?

Thinking about it now, it probably shouldn't.

 > [Constructor()] interface C { const short _prototype = 3; }
 > c=new C; c.prototype != 3; c.prototype.prototype === 3 ?
 > Is this what we want?


 > Temporary asside to a much earlier section because I needed to try to
 > apply it in order to make the preceding comments.
 > http://dev.w3.org/2006/webapi/WebIDL/#idl-names
 >> For all of these constructs, the identifier is the value of the
 >> identifier token with any single leading U+005F LOW LINE ("_")
 >> character removed.
 > It would help if the word 'underscore' was listed in this sentence,
 > it's perfectly acceptable to have it in a parenthetical.

OK.  I was going with the official Unicode name of the character,

 >> 4.5.5. Attributes
 >> For each attribute defined on the interface, there MUST be a
 >> corresponding property either on the interface prototype object
 >> or on every object that implements the interface, unless:
 > This blob doesn't do anything for 'prototype', which is odd. I'm 
pretty sure:
 > interface D { readonly attribute short _prototype; } and
 > interface E { [Unforgeable] readonly attribute short _prototype; }
 > would be unfortunate.


So I've just simplified things even further: I've added a sentence to
#idl-names disallowing any construct from having the identifier
"prototype", "constructor" or "toString".

 >> 4.5.6. Operations
 >> The characteristics of such a corresponding property are as follows:
 >> If O is not a platform object that implements interface I, throw a 
 > Can't O be a user object that implements [Callback] interface I? At
 > least for gecko, when you pass in a user object to a system thingy,
 > you can later get back your object as something that looks like a
 > platform object, but is really your user object. For the purposes
 > of security checks on later interfaces, you want it to fail any
 > check that does not have [Callback], but you should still be able to
 > generally make calls to it...
 > --- this is the first time i'm bringing this up, but it's possible
 > that it has ramifications throughout the spec.

The above check is just meant to prevent you from doing:

   var o = { };

Web IDL doesn't really talk about wrapping user objects as platform
objects.  If specifications wanted to require this, they could say this
in prose.  But I don't think we want it universally, do we?

 >> If there would still be conflicting property definitions, then it
 >> is undefined which consequential interface’s interface member that
 >> property on A’s interface prototype object corresponds to.
 > I found this to be hard to read..
 > Would the following be ok:
 > s/it.*to/the correspondence to a consequential interface for the
 > property on A's interface prototype is undefined/

Per above comments, that sentence has disappeared from

[part 5]

 >> It is the responsibility of specifications using Web IDL to state
 >> which global environment (or, by proxy, which global object)
 >> each platform object is associated with.
 > s/state which/state to which/; s/associated with/associated/

Sometimes I like eliminating sentence-ending prepositions, but I think
in this case it makes the sentence a little less clear.

 >> These properties are not “real” own properties on the object,
 > [global] You use `own` in a magic way which isn't really correct in
 > English. I'd almost want you to use <var>own<var> or <tt> or something
 > (or rephrase it) -- possibly even 'Own' instead of 'own'.

It's "own property" in the ECMAScript sense.  Not sure if it's necessary
to define this term -- it should be known if you are familiar with
ECMAScript, which you'll need to be if implementing.

 >> Future versions of the ECMAScript specification may define a total 
order for
 >> property enumeration.
 > Should there be a feature of the spec to enable one to satisfy WebIDL
 > in case the ECMAScript spec isn't compatible w/ 4.7.6 Property
 > enumeration?
 >   e.g., "If ECMAScript defines a total oder for property enumeration,
 > perform its steps instead of the following:"

I think I'll just update Web IDL in that case.

 >> For each exception field whose identifier is not “constructor”
 > I haven't quite figured out why this doesn't also mention "prototype"
 > (see similar comment on earlier objects).

Addressed per above comments.

 >> The value of the internal [[Prototype]] property of the exception object
 >> MUST be the exception interface prototype object from the global 
 >> the exception object is associated with.
 > s/the exception object is associated with/of the exception/

Earlier I describe objects as being "associated with" global
environments, so I think this wording here is OK.

 >> 4.12. Handling exceptions
 > The example here uses try{} blocks to catch each exception except for
 > the last, some of the earlier example blocks in the document did not
 > do this, i'd request that they be adapted to do so.

OK, I changed one earlier example where code to use a try block, where
otherwise the remaining code in the example wouldn't be run.

 >> 5. Java binding
 > This isn't a hat I've worn in about a decade.
 >> A conforming Java implementation MUST have a public Java interface
 >> corresponding to to every IDL interface that is supported, whose name
 >> is the Java escaped identifier of the IDL interface and which resides
 >> in the Java package corresponding to the interface’s enclosing module
 >> (or the default package, if there is no enclosing module).
 > The prose here is of a rather different form than the prose for
 > 5.2.20. Arrays — T[].

It is, but only because in 5.2.20 there are a few standardly named
methods that need to be defined on there.  I think if I showed an
outline of the Java interface definition for this section, it wouldn't
be that useful.

 >> If the IDL interface has one or more static operations declared on it,
 >> then there MUST also exist a public, abstract Java class, whose name is
 >> the concatenation of the identifier of the IDL interface and the string
 >> "Utils", and which also resides in the Java package corresponding to the
 >> interface’s enclosing module (or the default package, if there is no
 >> enclosing module). This class is known as the utility class for the IDL
 >> interface.
 > Nothing in the spec so far has prevented people from creating FooUtils
 > interfaces, and in fact, I believe some have been suggested. Which
 > makes me worry about collisions if someone has:
 > interface Foo {
 >   static void x();
 > }
 > interface FooUtils {
 >   void y();
 > }
 > I'm not quite sure why one would do this, but, oh well.
 > (I think WindowUtils has been mentioned for example...)

Fair point.  Some of my example IDL fragments define interfaces named
FooUtils, too.  I added a sentence saying that the Java class is named
_FooUtils in this case.

 >> 5.4.3 Attributes
 >> The tentative name of the method is a U+0067 LATIN SMALL G ("g") 
 >> followed by a U+0065 LATIN SMALL E ("e") character, followed by a 
U+0074 LATIN
 >> SMALL T ("t") character, followed by the first character of the 
 >> of the attribute uppercased (as if passed to the
 >> java.lang.Character.toUpperCase() method), followed by the remaining
 > If someone is stupid and has:
 > interface someI {
 > attribute boolean i;
 > attribute boolean I;
 > }
 > Will this mapping fall appart horribly? :)

Yes. :-)

I will define it so that the above will get names getI() for the first
one and _getI() for the second.

I will also forbid defining interface members with identifiers that
begin with an underscore entirely, for simplicity.

 > I was disappointed that I couldn't give you a dotless i here. (I
 > reached 'A. IDL grammar').


 >> 5.6. User objects implementing interfaces
 >> A Java user object that implements an IDL interface MUST be of a Java
 >> class that implements the Java interface that corresponds to the IDL
 >> interface.
 > interface A {};
 > interface B {};
 > A implements B;
 > If I have:
 > class MyA extends A {}, does the text above properly require me to in
 > fact do:
 > class MyA extends A implements B {} ?

You would need to use [Callback], but anyway user objects can only be
made from interfaces that do not have any consequential interfaces (so
that means the `A implements B` prevents [Callback] from being used in

I added some text and an example to that section to clarify inheriting
the implementation of an interface.
Received on Friday, 19 August 2011 00:44:05 UTC

This archive was generated by hypermail 2.3.1 : Wednesday, 8 May 2013 19:30:04 UTC