W3C home > Mailing lists > Public > public-webapi@w3.org > October 2007

Re: [Bindings] extended attribute for callback function interfaces?

From: Cameron McCormack <cam@mcc.id.au>
Date: Fri, 19 Oct 2007 15:36:20 +1000
To: Web APIs WG <public-webapi@w3.org>
Message-ID: <20071019053620.GB25826@arc.mcc.id.au>

Cameron McCormack:
> > Why would you want an interface object not exposed on the global object 
> > for these callback interfaces?  Firefox at the moment does have an 
> > EventListener interface object; Opera and WebKit don’t.

Ian Hickson:
> You wouldn't want it there because it would be useless.

For EventListener, yes this mightn’t be very useful, since
(nativeObjectImplementingEventListener instanceof EventListener) would
be false, and there aren’t any constants defined on EventListener that
would make it useful to have the interface object around for.

OK so this brings up a point.  Currently the document states that an ES
native object can implement an interface by having a host object with
properties (whose values are functions) for each operation on the
interface.  So if the interface had constants on it, these would not
need to be put on the native object:

  // -- IDL --
  interface B {
    const int x = 1;
    void f();
    void g();
  };

  // -- ECMAScript --
  var b {
    f: function() { },
    g: function() { }
  };

First, is it a good idea to allow this?  I don’t want to discriminate
against being able to implement interfaces in ES just because there are
constants defined on the interface, necessarily.  It does mean though
that you wouldn’t be able to refer to the constant of a native object
implementing B, but you would of a host object implementing B.  I don’t
know if I like this discrepancy.

(A way around that might be to require ES native objects implementing
interfaces that have more than just operations to be done like:

  var b = new B();
  b.f = function() { };
  b.g = function() { };

or something similar that sets up the prototype chain so that constants
are visible on the object.  That doesn’t work if you want to make a
native object implement more than one interface, though.)

> > For HTML 5 peculiarities, perhaps an [InhibitInterfaceObject] or 
> > something could be a more general solution.
> 
> That would be good, yes, though then we'd need two, one for that and one 
> to indicate that the interface should be Function-implementable.

Are these callback interfaces the only ones in HTML 5 that you need to
inhibit?

Jonas Sicking:
> > > It doesn't make much sense for interfaces that aren't callback 
> > > interfaces.

Cameron McCormack:
> > It seems to me to make as much sense as being able to implement such 
> > non-callback interfaces with an object with properties.

Ian Hickson:
> Oh no, having:
> 
>    myImageData = { width: 1, height: 1, data: [0, 0, 0, 0] };
> 
> ...makes much more sense than having:
> 
>    myCanvasGradient = function (offset, color) { ... };
> 
> In fact, CanvasGradient is the perfect example of why we don't want 
> Function to be randomly implementing interfaces.

I agree it’s pretty useless for ES to be implementing CanvasGradient,
since the opacity (in terms of the gradient parameters) of the object
prevents it from being able to be used by CanvasRenderinContext2D.  A
different design for CanvasGradient (one that had attributes for all of
the gradient parameters, for example) would make that possible.

> Then again, it's actually a good reason for not making any interface
> implementable by Object in JS too... can we have another attribute to
> stop that too? :-)

What about other languages?  Java for example cannot restrict who can
implement a given interface.  You likely want to throw an exception if
the CanvasGradient wasn’t created by a call to the context’s
create{Linear,Radial}Gradient() methods.  I think it’d be better to
handle the issue like this, than prevent ES from implementing that
interface at all -- perhaps some other spec/code wants to use
CanvasGradient for some other purpose, where it’s OK to be able to
implement it from ES, who’s to know?  I like to keep those sort of
options open, rather than preventing them.

> > But even if you were using the other way of implementing Callback:
> > 
> >   var a = …; // some object that implements A
> >   var c = { f1: function() { … } };
> >   a.f1(c);
> > 
> > then if Callback got another method later on you’d still have the same 
> > problem; ‘c’ doesn’t implement Callback.  So you still need to 
> > make a change.
> 
> ...except that your code would still work. The latter shouldn't raise a 
> TypeError. We can't ever make the latter raise a TypeError, as that would 
> be breaking back-compat with legacy code, by that point.

In that case, what’s the rule for determining if a native object has
implemented a given interface?  For the above example, would it be
just if it’s an object that has properties (whose values are functions)
that correspond to the methods that A.f1() happens to need to call?

-- 
Cameron McCormack, http://mcc.id.au/
	xmpp:heycam@jabber.org  ▪  ICQ 26955922  ▪  MSN cam@mcc.id.au
Received on Friday, 19 October 2007 05:36:34 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Tuesday, 8 January 2008 14:18:58 GMT