Re: Solving the "how do I tell whether I have an HTML element?" (or image element, or whatever) problem

On Dec 31, 2012, at 8:33 PM, Boris Zbarsky wrote:

> Note: es-discuss is bcced, but please reply to public-script-coord.
> 
> The fact that instanceof for "standard classes" is completely broken when multiple globals are involved has come up yet again, as Gecko converts to WebIDL bindings.

I'd argue that this is an ECMAScript issue rather than a Web API issue.  If one indeed considers instanceof broken when multiple globals is involved then it is broken for everything, not just Web APIs.  It isn't clear that fixing it for Web APIs while leaving it broken for everything else actually benefits JavaScript programmers.  Rather than trying to fix it via WebIDL bindings perhaps it would be better to lobby TC39 to fix (or replace it) for everything.

> 
> The reason for that is that currently in Gecko's DOM bindings instanceof where the RHS is a DOM interface object does magic that returns true if the LHS is a platform object implementing that interface (in the WebIDL sense).  We initially tried to not do that for the WebIDL bindings and have had to put it back in for now because it turned out that there was a fair bit of Gecko-specific content that relied on this behavior.
> 
> That said, I would like to figure out a way forward here, and figure it out sooner rather than later so we don't have to change said Gecko-specific content more than once.
> 
> The obvious options seem to be:
> 
> 1)  Hack instanceof as Gecko has in the past.  This is actually a bit of a pain to implement even in Gecko, without changes to SpiderMonkey, because function objects can't have the magic behavior the RHS needs above in SpiderMonkey at the moment.
> 
> 2)  Add something like Array.isArray to all WebIDL interface objects. HTMLImageElement.isHTMLImageElement is a bit wordy, though... HTMLImageElement.isInstance() would be simpler, but doesn't match the existing isArray pattern.
> 
> 3)  Do something else.  What?
> 
> Thoughts?  I'm particularly interested in things that other UAs are willing to implement (e.g. if #1 above is a non-starter for them, there's no point even discussing it in terms of specs).


In the current ES6 drafts, instanceof is  extensible on a per class (really constructor) basis.

This works as follows:

     (obj instanceof Ctor)   is defined to produce the boolean result of calling:
                     Ctor[hasInstance_privateSymbol](obj)

In the spec. we refer to the method that is called as @@hasInstance

The default  @@hasInstance behavior is the traditional ES instanceof check.  However, all it takes to change that is to define an alternative @hasInstance method on a constructor.

For example, let say for constructor Foo you want hasInstance to work cross frames and to be insensitive to the prototype chain configuration. You might do this by defining a private symbol, let's refer to it as @@FooBrand and make sure that it is known to the Foo implementation that is used in all frames. Whenever a Foo instance is created by Foo it would create a frozen @@FooBrand keyed property on the instance.

The definition of @@hasInstance for Foo could then be:

Foo[hasInstance_privateSymbol] = function (obj) {
   if (typeof obj !== "object") return false;
   if (obj ===null) return false;
   return Object.getOwnPropertyDescriptor(obj,FooBrand_privateSymbol) !== undefined
};

(I've gloss over the details of how hasInstance_privateSymbol and FooBrand_privateSymbol) would be imported.  If Foo was implemented natively, they would be communicated at that level.)

Allen





> 
> -Boris
> 
> P.S.  The obvious "foo instanceof foo.ownerDocument.defaultView.HTMLImageElement" hack only works for nodes, and even then fails if foo.ownerDocument is an XHR response document or something else without a Window, so it's not a viable solution even if it were too not convoluted to really recommend with a straight face.
> _______________________________________________
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
> 

Received on Tuesday, 1 January 2013 22:57:33 UTC