Re: Detecting the "type" of a DOM object

On Jun 21, 2012, at 11:28 AM, Boris Zbarsky wrote:

> On 6/21/12 2:14 PM, Allen Wirfs-Brock wrote:
>> How often do you have (application) code that actually needs to discriminate between, for example, a DOM Node and a Date?
> 
> Any time you have a method that takes an argument it expects to be a Node and it wants to do argument validation up front instead of running into exceptions partway through when it's in an inconsistent state.

This is usually just wishful thinking  that is trying to apply static typing concepts to a dynamic language.  What does an instanceof test actually guarantee about an object?  Not much.  For example, my reading of WebIDL says that most operations exists as configurable prototype object methods.  These are over-ridable on a per instance basis and replaceable at the prototype level. So an simple instanceof test, any way you define it, isn't going to tell you anything about the future (or perhaps even the current) behavior of the object.  It may or may not have the actual methods or the implementations you expect to be there. 

A comprehensive runtime nominal type check is usually very expensive (recursively validate every property (including inherited) of an object against an expected set), fragile, and overkill.  In addition such checking is typically performed redundantly, with the same object being expensively check multiple times.  I've seen many naively  implemented large OO systems where such checking was subsequently identify as the major performance bottleneck.

Dynamic languages perform safety checks on every dynamic method/property access.  That's the validation backstop that dynamic language programmers can depend up.  In the (I argue rare) situations where pre-validation is necessary it needs to be carefully thought-out on a per situation basis:  What is the minimum requirements that need to be validated? What is the least expensive way to do that validation?  How long  does the validation remain guaranteed to be still hold? 

There probably isn't a general language level solution to this for dynamic languages. If you aren't going to work through all those design issue for your specific application situation then you probably shouldn't even be thinking about early argument validation and just let the language engine do its job.

> 
> I've also seen requests for this from people doing introspection (for debugging, error reporting, etc).

Those are different use cases, so I'm not exactly sure what they are saying they need.  Certainly tools generally have the flexibility of doing much more extensive analysis of the objects they encounter then would make sense in hot code. 

> 
>> We also have the issue of what we mean by "is a".  Are we talking about behavioral equivalence or are you talking about identical implementation.
> 
> The former, in this case (witness the desire to have a Document test true for "is a Node").  If you just want identical implementation, you can get that now for WebIDL-defined stuff using Object.prototype.toString hackery.

Ok, but if you want behavioral equivalence (which I should probably define, roughly I mean exposes the same interface) then it can be based upon a constructor relationship (multiple different constructor can produce objects that are all behaviorally equivalent) or implementation mechanisms such as the [[Prototype]] chain.  

> 
>> For example, in JS you might define:
>> 
>> function isDomNode (obj) {
>>    return 'nodeType' in obj;
>> }
> 
> That tells you nothing about what will happen when you try to call insertBefore with obj as an argument....

If you care about insertBefore you can check for it instead of nodeType.  But neither gives you any guarantees about what insertBefore will actually do when you call it. Short of a secure mechanism that guarantees you will call a known and trusted implementation of insertBefore (and everything is uses or depends upon) you will never know for sure what insertBore is going to do. Perhaps you can get there using SES-style OCAP techniques.  But WebIDL is not defined that way and it isn't at all clear that it would be acceptable to the world to do so.  


> 
>> If an non-Node object has reached a point in the code where you expect an object that behaves like a Node you already have a bug.
> 
> Well, your _caller_ has a bug.  The idea is to catch the bug early and fail safe.  Especially for library code that has to deal with untrusted inputs.

What's "safe".  The language guarantees memory safety.  If you are worried about maintaining the invariants of you internal data structures, don't allow user code to directly access them. There are many situations where fail late is better than fair early.  See, for example, http://www.cag.lcs.mit.edu/~rinard/paper/osdi04.pdf 

This isn't a new issue. I wrote about it here http://www.wirfs-brock.com/allen/posts/379 . Basically, there is a need for a secure and validating layer of the web platform.  But it isn't going to work if we try to place it at the level of individual web apis. Issues like instanceof based validation are just a distraction.  Instead we really need to define the high integrity kernel layer of the web platform, and then let things above that layer take care of themselves.  Most web apis should be thought of as frameworks whose integrity are not essential to the overall web platform.  If a developer breaks one, its their problem.

Allen

Received on Thursday, 21 June 2012 20:13:12 UTC