Dynamic behavior attachment does not work, subtyping elements could work (Was: Re: Behavior Attachment Redux, was Re: HTML element content models vs. components)

Hixie wrote:

<snip>
… The pure JS side of things,
which is all that is needed for what we're talking about here, needs
nothing more than just adding a prototype, something which is not only
well-supported by all browsers, but defined in increasingly careful
detail. Interoperability is only improving here, and there seems to be no
desire to remove it -- quite the opposite, we're actively working on
making it more useful for authors.
</snip>

I think you are wrong about this.

WebIDL is making it easier to add and hook methods to a specific prototype
that already exists. *Adding* a whole new link in the prototype (which is
what I guess you mean by "just adding a prototype"—happy to go into the
problems with modifying existing prototypes!) is difficult today, and Web
IDL makes it even harder. These factors are working against you:

1. Some implementations have a writable __proto__ property on objects, that
let you set its prototype. However this isn’t portable—-__proto__ is not in
ECMA-262; theres Object.getPrototypeOf but not setPrototypeOf. Messing with
individual instances isn’t particularly robust or scalable anyway, because
if an instance leaks out before you update its prototype, then confusing
bugs result.

2. Web IDL locks down interface’s prototype property—S 4.5.1 interface
object must also have a property named “prototype” with
attributes { [[Writable]]: false, [[Enumerable]]: false,
[[Configurable]]: false }—so adding a prototype object within the existing
prototype chain of interfaces is unavailable.

3. Web IDL operations and attribute getter/setters validate the this pointer
this way, eg operations—S 4.5.6 [stuff about ImplicitThis] O is the result
of calling ToObject on the this value … If O is not a platform object that
implements interface I, throw a TypeError. So adding a prototype object off
the end of an existing prototype chain is also not possible (if you want the
property accessors and operations to work!)

Hence a binding layer can not make use of this, because it does not work.

That is why we are proposing something we have been calling
HTMLElement.register.

It doesn’t rely on #1—you set up prototype chains on constructors, it
doesn’t mess with __proto__ on instances. It works with #2—you add new
prototype objects to the end of the prototype chain. ie it is subtyping, not
mixins. It works with minimal impact to #3. Attribute getters and setters
and operations continue to validate "this" they way they are speced. We just
specify Interface [[Call]] in more detail to allow HTMLElement.call(this).

Dominic

On Thu, Sep 29, 2011 at 8:02 AM, Ian Hickson <ian@hixie.ch> wrote:

> On Wed, 28 Sep 2011, Boris Zbarsky wrote:
> > On 9/28/11 4:02 PM, Ian Hickson wrote:
> > > I don't buy the argument that an element's API can't change.
> >
> > To be more precise, such changes are very undesirable.
> >
> > > We have many counter-examples already in the platform, for
> > > example<object>'s API can change dynamcially as it loads new plugins
> >
> > This is actually a serious problem in practice, for both implementors
> > and consumers.  The behavior here is not very interoperable outside the
> > simplest cases last I checked.
> >
> > > XBL in Mozilla causes elements to change APIs on the fly
> >
> > We consider this to have been a design mistake that complicates both
> > implementation and use.  We have absolutely no desire to perpetuate it.
>
> There are specific problems in both those cases because of interaction
> with the C++ layer, as far as I can tell. The pure JS side of things,
> which is all that is needed for what we're talking about here, needs
> nothing more than just adding a prototype, something which is not only
> well-supported by all browsers, but defined in increasingly careful
> detail. Interoperability is only improving here, and there seems to be no
> desire to remove it -- quite the opposite, we're actively working on
> making it more useful for authors.
>
> IMHO this is the kind of thing that it makes imminent sense for a binding
> layer to make use of.
>
>
> > > Furthermore, we cannot for performance reasons require that the
> > > component library be loaded before the page is parsed, since that
> > > would mean that loading an HTML page would be blocked on loading a
> > > subresource. We already have this problem with both style and scripts,
> > > and it is a performance nightmare.
> >
> > I agree that it can cause performance problems, but as you note we
> > already have this with <script>, and speculative parsers are getting
> > pretty good.
>
> If you add an RTT to the page load, it doesn't matter how good your parser
> is. You're going to be slower than not having the RTT unless your page is
> absolutely huge.
>
>
> > Using an attribute to declare the binding could work if we make its
> > value immutable or if we make changes to its value have no effect.
>
> For use cases consisting of creating new or augmented widgets, that's fine
> by me. We already have plenty of precedent for attributes whose changes do
> nothing, for example <script src> and, most recently, <html manifest="">.
>
> For use cases that are intrinsically presentational and dynamic, like
> layout managers, I don't think the markup should need to be changed
> (except in the <head>, to opt-in to the binding and style sheets).
>
> Those use cases probably don't need the elements to actually expose an
> API, though, so maybe that's a non-issue. They do need to be able to hook
> event handlers, read existing APIs, and modify the presentation.
>
> --
> Ian Hickson               U+1047E                )\._.,--....,'``.    fL
> http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
> Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'
>
>

Received on Thursday, 29 September 2011 01:34:35 UTC