Detecting the "type" of a DOM object

David Bruant bruant.d at gmail.com
Fri Jun 22 11:01:41 PDT 2012


Le 22/06/2012 18:13, Allen Wirfs-Brock a écrit :
> I'm going to try to move the discussion of this issue to es-discuss
> via a separate message as it is mostly about Proxy design. (bcc'ing
> public-script-coord)
>
> the start of this subthread is the following which identifies that
> historically the [[HasInstance]] extension point has been used (at
> least conceptually) to provide alternative instanceof semantics.
I'd like to point out that whether the trap should be on the LHS or RHS
of the instanceof expression is a non-trivial choice. If one is chosen
over the other, I'd be interested to see this choice being justified.

>> I don't think the new direct proxies API impacts this strawman, so
>> technically I see no reason why proxies can't have a [[HasInstance]]
>> trap if needed.
>
> I agree, I don't see that it presents any technical hurdles.
There is a potential security issue. From the wiki [1] (in the case
where the instance is a proxy trapping on instanceof): "Security issue:
the handler is given a reference to the function object (the right-hand
side of the instanceof operator). This gives the handler the ability to
generate new instances of that function. "

In my opinion, the issue stands if the choice is to have either the LHS
or RHS of instanceof to trap on instanceof. The more general issue isn't
about generating new instances, but about an object gaining access to
another object it didn't have access to before the instanceof
evaluation. Both cases result in a capability leak.

To be more precise, currently, when you write "a instanceof b", you
don't expect either a or b to leak. This property should probably be
preserved even with proxies.


Here is a proposal that enable custom instanceof behavior and doesn't
leak either a or b:
Any object may (it's not compulsory) have an internal [[instanceofHint]]
property (as usual, name isn't set in stone).
Any function may have an internal [[instanceofMatch]] method. This
method takes a value and returns a boolean. The value will be the
[[instanceofHint]] property of an object

[[HasInstance]](V) becomes:
(Assume F is a Function object which has this [[HasInstance]] property)

1) If V is not an object, return false.
2) If V has an internal [[instanceofHint]] property and F has an
internal [[instanceofMatch]] method, return
F.[[instanceofMatch]](V.[[instanceofHint]])
3) else goto step 2 of the ES5.1 [[HasInstance]] algorithm and continue
from there.

By default, objects do not have an [[instanceofHint]] or
[[instanceofMatch]] property, so backward-compatibility is kept for
ECMAScript 5 objects.
Proxies can have a way to provide both an [[instanceofHint]] and
[[instanceofMatch]] internal properties in their handlers to enable
custom instanceof behavior. The trap for [[instanceofMatch]] is never
handed objects, but only [[instanceofHint]], so as long as these do not
leak instances, there cannot be a leak.
For WebIDL objects, one way to use this is to say for instance:
* Instances of interface A objects have 'A' as [[instanceofHint]]
* The [[instanceofMatch]](v) method of constructors is roughly:
return true if v refers to one of the constructor subclass and false
otherwise.

In that case, document instanceof Node would return true (regardless of
which global Node or document came from), because
document.[[instanceofHint]] would be 'HTMLDocument' and
Node.[[instanceofMatch]] would recognize that as a subclass of Node.

Instead of adding a new [[instanceofHint]] internal property, maybe the
[[NativeBrand]] could be reused.

David

[1]
http://wiki.ecmascript.org/doku.php?id=harmony:proxies#interaction_with_instanceof


More information about the es-discuss mailing list