W3C home > Mailing lists > Public > public-webapps@w3.org > October to December 2008

[WebIDL] Flattening multiple inheritance in prototypes

From: Cameron McCormack <cam@mcc.id.au>
Date: Sat, 8 Nov 2008 23:08:05 +1100
To: public-webapps@w3.org
Message-ID: <20081108120805.GA15966@arc.mcc.id.au>

Hello WG.

In response to some previous feedback, I’ve removed the suggestion from
Web IDL to perform some prototype trickery to simulate multiple
inheritance, and added a proposal that introduces some extended
attributes that help control how multiply inherited interfaces (and host
objects that implement multiple interfaces) have their prototype chain
set up.  This prototype chain is now required.  I’m open to arguments
about loosening this back up again to not require particular
[[Prototype]] values, but to require something that acts mostly the
same.

To summarise:

* A [PrototypeRoot] extended attribute can be used on an interface to
indicate that descendent-or-self interfaces are the “main” interfaces
whose interface prototype objects should make up the prototype chain.
This would be used on Node, for example.

* An [ImplementedOn] extended attribute can be used to state that all
objects implementing X also implement Y.

* Simple single inheritance results in a simple prototype chain.  For
example with:

  interface A { … };
  interface B : A { … };
  interface C : B { … };

you’d have:

  A.prototype = { … }
  A.prototype.[[Prototype]] = Object.prototype
  B.prototype = { … }
  B.prototype.[[Prototype]] = A.prototype
  C.prototype = { … }
  C.prototype.[[Prototype]] = B.prototype

and an instance of C (that doesn’t implement anything other than A, B
and C) would have its [[Prototype]] set to C.prototype.

* Multiple inheritance results in the mixin interfaces being flattened
at particular places in the prototype chain.  For example with:

  [PrototypeRoot]
  interface Node { … };
  interface Element : Node { … };
  interface HTMLElement : Element { … };

  [ImplementedOn=Node]
  interface EventTarget { … };

  [ImplementedOn=Element]
  interface NodeSelector { … };

you’d have:

  Node.prototype = { … }
  Node.prototype.[[Prototype]] = Object.prototype
  _1 = { /* properties for EventTarget */ }
  _1.[[Prototype]] = Node.prototype
  Element.prototype = { … }
  Element.prototype.[[Prototype]] = _1
  _2 = { /* properties for NodeSelector */ }
  _2.[[Prototype]] = Element.prototype
  HTMLElement.prototype = { … }
  HTMLElement.prototype.[[Prototype]] = _2

See:

  http://dev.w3.org/2006/webapi/WebIDL/#interface-prototype-object
  http://dev.w3.org/2006/webapi/WebIDL/#host-objects
  http://dev.w3.org/2006/webapi/WebIDL/#ImplementedOn
  http://dev.w3.org/2006/webapi/WebIDL/#PrototypeRoot

As a consequence of this, modifying the interface prototype object for
interfaces that are used only as mixins, such as EventTarget, won’t do
anything useful because their properties will be copied into separate
mixin prototype objects (like the _1 above) in an interface’s prototype
chain.

(We could require that modifications to Event.prototype result in
corresponding modifications to the mixin prototype objects like _1
above, though it feels a little hacky.)

As always, comments (from anyone but from implementors in particular)
are welcome.

Responses to a couple of old mails to the list follow.


Anne van Kesteren:
> > [In another thread I requested functionality for a]
> > way to define what the "base" interface it is which has the same
> > effect but might be cleaner as it also removes the need to say
> > "objects implementing interface X must also implement interface XY".

Cameron McCormack:
> I didn’t add that one.

And now I did, as [ImplementedOn].

Ian Hickson:
> [re lack of mandated behaviour for prototype chains]
> I understand what you're saying, but I'd still rather have any black box 
> behaviour be unambiguous. (Non-black-box behaviour is irrelevant.)

So this is specified precisely now.

Ian Hickson:
> There are two use cases for interface flattening that I think it would be 
> useful for the Web IDL spec to address.
…
> There are two related cases. One is objects that implement multiple 
> interfaces that are available "using binding-specific casting methods", 
> as, for instance, EventTarget. Another is inheritance, e.g. the way 
> HTMLAnchorElement inherits from HTMLElement. The latter is supported in 
> IDL. The former currently doesn't really easily fit into JS, it would be 
> nice if it could be made somehow more consistent (e.g. so that you could 
> override the EventTarget methods and affect all objects that implement 
> EventTarget at once).

This is now handled explicitly, but as mentioned above you can’t do

  EventTarget.prototype.x = y

and expect it to do something useful.

-- 
Cameron McCormack ≝ http://mcc.id.au/
Received on Saturday, 8 November 2008 12:08:55 GMT

This archive was generated by hypermail 2.3.1 : Tuesday, 26 March 2013 18:49:28 GMT