Cross-global instanceof

Allen Wirfs-Brock allen at wirfs-brock.com
Thu Oct 31 17:50:35 PDT 2013


On Oct 31, 2013, at 2:56 PM, Andrea Giammarchi wrote:

> Sorry, secure was actually "reliable", as being secure about the type, not about security itself.
> 
> A case where I do use instanceof is, example, with new String to easily decide later on what to do with such object that should not be treated as such.
> 
> The script does resolve circular dependencies backward and forward out of JSON.stringiy and JSON.parse that do create objects from the current realm.
> 
> Nothing else than `instanceof` is as usable/useful in current ESX spec for same purpose in terms of performance and reliability.
> 
> https://github.com/WebReflection/circular-json/blob/master/src/circular-json.js#L108
> 
> Just one case, still `instanceof` is used a lot and usually for good reasons, ...

Well I promised I'd explain how I'd eliminate use of 'instanceof' so here goes. Note that since this is in the context of talking about possible ES extensions I'll assume those are available.

First, you're using (lines 20) String wrapper objects(with the name String aliased to $String)  to pass around string values that require special processing.  Personally, I find this a little too subtle.  In ES6 I'd do this way instead:

const isSpecialString = Symbol.for("isSpecialString");  //registration proposal in http://esdiscuss.org/topic/comments-on-sept-meeting-notes#content-76 
class SpecialString extends String {
   constructor(str) {
       super(str.slice(1)) //move string preprocessing into constructor
   }
   [isSpecialString]() {return isSpecialString in this};  //not really intended to be called
}

In line 110 I'd use
    Array.isArray(current) 
instead of 
    current instanceof Array 
(note that JSON processing was one of the original use cases that motivated Array.isArray)

In line 114, instead of
 current instanceof $String ?
i'd use
 isSpecialString in  current ?    //note works cross-realm, if that is what is desired. 

I may be missing something WRT possible cross-realm issues, but in line 126 I'd replace
   current instanceof Object
with
   typeof current ==  'object'
but, I'm really thinking that I must be missing something that motivated your use of instanceof.  Is the supposed to be a Realm check?

> ... not because we are all bad developers (I hope ...)

No, but possibly developers who learned (or were taught be people who learned) about such things in a language context where static nominal class tests make more sense.

Allen




> 
> Cheers
> 
> 
> 
> On Thu, Oct 31, 2013 at 2:32 PM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:
> 
> On Oct 31, 2013, at 1:58 PM, Andrea Giammarchi wrote:
> 
>> I think the question is legit and this is a weak check
>> 
>> `'throw' in possibleGenerator`
>> 
>> specially if you have Dictionary like objects around ...
> 
> And why would such an object be passed into a context where you expect to have a generator?  That would probably be an upstream bug and cause a downstream failure.  Presumably you should have tests that look for such failures.
>> 
>> 'length' in object does not tell you much, does it? 
>> 
> 
> who is that relevant?  If you need to condition something on the existence of a length property, you can.  But in most situations you don't want to do such tests.  Just access the property and use it/call it.  It it is the right kind of object things will work.  If it is the wrong kind, it is somebody's bug.  
>> `Object.prototype.toString` is abused all over client/server libraries/utilities since ducks sometimes might look like gooses too.
> 
> Any, quite likely, most commonly used for unnecessary nominal type tests.
> 
>> So eventually would you don't want developers to really know what they are dealing with and promote weak feature detections instead? It might work, but that ain't secure.
> 
> Yes, no. Good OO is about letting go of knowledge of an objects implementation.  In most cases you should only be concerned about the object behavior you will use and not care about who implemented it or how or whether or not there are multiple interoperable implementations operating.  But you should be feature testing for the behavior you depend upon.  Just invoke it.  It the method need isn't there you are usually going to get an exception, typically sooner that latter.   Feature detection shouldn't be  used as poor-man nominal type checking (where you throw if it fails).  You should only use feature checking, when you have real alternative paths to take depending upon the presence of the feature. 
> 
> "Secure"?  What kind of security for what purpose? Every little about JS is secure.
> 
> Of course, there really are some places where you really do need to do a brand check for a specific object implementation.   In those cases, the implementation of the object should include brand checking in its design and expose an appropriate function for doing the check.  But a general purpose mechanism is an attractive nuisance, and probably doesn't actually do the check you need for your specific use case.
> 
>> 
>> I still prefer `instanceof` for better performance since I don't usually work with different realm but I also would like to have an `Object.is(SomeClass, object);` facility instead of the boring, slow, and inappropriate `{}.toString.call(obj)` check.
> 
> Show me real use cases and I'll try to explain with the check isn't needed.
> 
> Allen
> 
> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20131031/69541025/attachment.html>


More information about the es-discuss mailing list