Cross-global instanceof
Le 31/10/2013 16:38, Anne van Kesteren a écrit :
This keeps coming up. Last instance: mxr.mozilla.org/mozilla-central/source/dom/base/ObjectWrapper.jsm#16
We have it for
Array
usingArray.isArray()
.
Array.isArray
is not at all equivalent to instanceof. Not even related.
Object.create(Array.prototype) instanceof Array === true
var a = [];
a.__proto__ = null;
Array.isArray(a) === true;
We need both types of checks, one for "is such object in the prototype chain?" and the other for "how is this object magic?" (Array, Date, WeakMap, File, whatev's). The source code you're linking to seems to want the latter.
It is unclear why the arguments for arrays not apply to other types of objects, such as array buffers, nodes, blobs, files, etc.
We could introduce something like
Object.crossGlobalInstanceOf(instance, type)
which checks @@crossGlobalBrand or some such which works for built-ins and is also usable by jQuery and the like.
I'm not sure it's worth making it work for jQuery. This is trying to make a good use of same-origin multi-global which shouldn't exist in the first place. Keeping same-origin access as it is and encouraging people to add @sandbox even on same-origin iframes seems like a better idea.
Should the addition be a nicer Object.prototype.toString.call
?
On 10/31/2013 8:50 AM, David Bruant wrote:
I'm not sure it's worth making it work for jQuery. This is trying to make a good use of same-origin multi-global which shouldn't exist in the first place. Keeping same-origin access as it is and encouraging people to add @sandbox even on same-origin iframes seems like a better idea.
Should the addition be a nicer
Object.prototype.toString.call
?
You're right, it's not instanceof
. But I definitely think the argument
can be made that there is a need for checking if something is of a
certain class. I'm finding myself wanting things like isGenerator
and
isGeneratorFunction
, for example. There's countless examples of people
re-purposing Object.prototype.toString
to serve this functionality ad hoc.
What are the use cases for things like 'isGenerator'. When and why would you need to know that an object upon which you are going to invoke the Iterator interface was/wasn't implemented by a generator. If the reason is to know whether or not you can use the throw method (the only real difference between the generator object interface and the Iterator interface) you can test:
'throw' in possibleGenerator
In general this sort of isFoo
or obj.constructor === Foo
class test is a bad smell in dynamic class based languages and tends to be a reflection of static nominal type thinking (which is fine in its own context, but JS is has a dynamic class model).
I think the question is legit and this is a weak check
'throw' in possibleGenerator
specially if you have Dictionary like objects around ...
'length' in object does not tell you much, does it?
Object.prototype.toString
is abused all over client/server
libraries/utilities since ducks sometimes might look like gooses too.
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.
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.
Just my thoughts, as usual.
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 anObject.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.
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.
WebReflection/circular-json/blob/master/src/circular-json.js#L108
Just one case, still instanceof
is used a lot and usually for good
reasons, not because we are all bad developers (I hope ...)
On Oct 31, 2013, at 2:56 PM, Andrea Giammarchi wrote:
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, in which place on current known universe, when you parse a JSON.string, your reviver function receives objects from another realm, exactly?
That logic is bypassing and full-satisfying JSON.parse revival expectations
returning object later on checked as instanceof String in order to
differentiate and revive them differently and the same is done for Object,
where typeof
would create a disaster in that tested logic with just a
null
value plus CircularJSON is fully compatible with ES3 and Mr D.
Crockford JSON polyfill too so .... since we'd like to have shimmable code
and Symbols are a no-go, do you still think instanceof is not needed at all?
'cause just this null instanceof Object
is a good reason to use it when
objects are expected in a revival loop, imho.
Thanks, regardless, for spending some time on it.
On Nov 1, 2013, at 2:46 PM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:
Allen, in which place on current known universe, when you parse a JSON.string, your reviver function receives objects from another realm, exactly?
Please try to keep the discourse polite.
That said this is fairly trivial
<realm a>
function reviver(…) { … }
</>
<realm b>
JSON.parse(… <realm a>.reviver …)
</>
now the realm of the objects created by the JSON object differ from the realm that the reviver function is working in.
Sure, so Allen asked me a real case to show, and I've done it. Now you
please show me a real case when you pass a revival function to JSON.parse
that is from another realm, explaining why, as I've done for mine, thanks.
Best
also, your reviver would receive objects from the realm I am checking with that code ... so your reviver will receive object from the expected realm ... just to clarify, for future readers.
Still all ears listening to that case I've never, honestly, considered!
On Nov 1, 2013, at 7:23 PM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:
also, your reviver would receive objects from the realm I am checking with that code ... so your reviver will receive object from the expected realm ... just to clarify, for future readers.
I don’t understand what you’re saying here
if your reviver is in realm A, and says
function reviver(foo) {
…
if (foo instance of Array) alert(“Array!”)
...
}
And realm B says
JSON.parse(…, realm A.reviver)
You will never get to the alert.
As far as use cases, i recall multiple websites using invisible iframes as “modules” where multiple realms would use a shared group of functions from a single realm
I have no idea who is doing that and why but yes, in that case I would never have used instanceof so my example is still valid as use case itself.
On Fri, Nov 1, 2013 at 12:50 AM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:
[isSpecialString]() {return isSpecialString in this};
So this is basically what we have for DOM objects right now. And what
we're asking for is having this elevated to language-supported
construct. Be it in the form of a method or something else. It's not
really clear why sometimes you would use if brand in obj
and other
times Array.isArray(obj)
. Seems rather messy.
On Nov 1, 2013, at 10:40 AM, Anne van Kesteren wrote:
So this is basically what we have for DOM objects right now. And what we're asking for is having this elevated to language-supported construct. Be it in the form of a method or something else. It's not really clear why sometimes you would use if "brand in obj" and other times "Array.isArray(obj)". Seems rather messy.
Array.isArray is a legacy artifact so I'm not going to try to generalize from it.
But, in general, the distinction is between asking "does this object appear to expose the behavior I need" and "is this object an instance of a specific known implementation of the behavior I need". Let's call the first question "duck typing" and the second "branding". Duck typing is a weaker test but allows for a lot of flexibility and extensibility. Branding gives you reliable knowledge about certain aspects of a branded object. But it is less flexible and and systems that extensively using branding are often harder to extend. IMO branding is over used.
Array.isArray is a specific brand test based upon how the implementation of how property definition interacts with the value of the 'length' property.
ES currently proves lots of ways to do duck type testing. Built-in objects (including host objects) can implement branding and brand testing using various techniques but ES currently (including ES6) is very limited in its language level sort for reliable branding. The best we have to offer in ES6 is WeakMaps. In the future, we probably will add mechanism that make it easier to define branded objects defined via ES code.
But, before you brand something really think carefully about why you need such a brand. It may not really be necessary.
Allen I think we all agree duck typing is more flexible, powerful, easy,
etc etc ... but since you mentioned, how would do distinguish between a
Map
and a WeakMap
without passing through the branding check ?
That's a very good example indeed, 'has' in obj
or 'set' in obj
does
not grant you any behavior with the signature itself (e.g. WekMap
does/did not accept primitives as key)
AFAIK WebIDL is entirely based on branding, regardless it's a good or a bad thing, that's the way W3C describes "things" since quite ever (and implement them in Java too ... anyway)
Why there's no easy way to check for branding if not abusing
Object.prototype.toString
?
If so many libraries are using it because of the cross realm, maybe there is a need for some similar mechanism and implemented in core would make everybody life easier/faster ?
The option you give us is: keep abusing Object.prototype.toString
...
that's OK but it seems to be a dirty solution.
On Fri, Nov 1, 2013 at 12:16 PM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote:
The option you give us is: keep abusing
Object.prototype.toString
... that's OK but it seems to be a dirty solution.
In ES5, Object.prototype.toString was a reliable brand check. It no longer is in ES6.
Thanks Mark, so how is anyone supposed to be sure about or check a Brand in ES6 then?
For the ES6 builtin types, I have no idea.
For abstractions you define yourself, your abstraction can brand its objects using an encapsulated WeakSet or WeakMap. This will work, but with two problems:
-
Awkward syntax until more directly supported by ES7 relationships.
-
Sucky performance until Weak* implementations transpose their internal representation, as recommended by the relationships strawman. Note that implementations should do this transpose asap, as it is purely an optimization fully applicable to ES6. It has no dependence on the rest of the relationships strawman.
On Nov 1, 2013, at 12:16 PM, Andrea Giammarchi wrote:
Allen I think we all agree duck typing is more flexible, powerful, easy, etc etc ... but since you mentioned, how would do distinguish between a
Map
and aWeakMap
without passing through the branding check ?That's a very good example indeed,
'has' in obj
or'set' in obj
does not grant you any behavior with the signature itself (e.g.WekMap
does/did not accept primitives as key)
You can behaviorally distinguish between a Map and a WeakMap by the presence or absence of the 'forEach' or @@iterator property. But why would you need to do that sort of discrimination?
If you need a map that is Iterable and somebody passes you a WeakMap that's a bug. An exception will be thrown when you try to iterate over it. Similarly, if you need a map that accepts primitive values as keys and somebody passes you a WeakMap that's also a bug and will result in downstream exceptions. What are the use case where you would want to accept either a Map or WeakMap and take different control paths depending upon which as passed?
AFAIK WebIDL is entirely based on branding, regardless it's a good or a bad thing, that's the way W3C describes "things" since quite ever (and implement them in Java too ... anyway)
So? Why should that restriction be lifted in a manner that allows multiple independent implementations or extensions of DOM interfaces to peacefully coexist.
Why there's no easy way to check for branding if not abusing
Object.prototype.toString
?
Because there is no single semantics for branding. What do you want you brand to mean. For example, all of the branding in ES6 is subclass friendly. Maps are branded and most Map methods will only work on Map branded objects. But subclass instances of Map are (by default, you can make it otherwise) are also branded such that the Map methods will work for them.
In other circumstances, a developer may decide that they do not want subclass instances to share branding with a superclass.
In some cases it may be desirable for an individual object to carry multiple brands.
You can look at Realm associations of ES functions as form of branding...
What is the single easy test that encompasses all of these use cases, and others
If so many libraries are using it because of the cross realm, maybe there is a need for some similar mechanism and implemented in core would make everybody life easier/faster ?
Arguably, the real issue here is the ad hoc semantics of Realms that have been implemented in browsers and the same-but-different built-ins that can be referenced cross Realms.
The option you give us is: keep abusing
Object.prototype.toString
... that's OK but it seems to be a dirty solution.
As Mark mentions in a subsequent message. ES6 O.p.toString only provides brand checking for legacy ES<=5 built-ins. It won't brand check Maps for you. That is intentional.
On Nov 1, 2013, at 1:11 PM, Mark S. Miller wrote:
For the ES6 builtin types, I have no idea.
Most branded ES6 built-ins have non-destructive brand-checking methods that call be used to perform brand checks.
For example,
function isMap(obj) {
try {Map.prototype.size.call(obj); return true} catch (e) {return false}
}
On Fri, Nov 1, 2013 at 4:03 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:
As Mark mentions in a subsequent message. ES6 O.p.toString only provides brand checking for legacy ES<=5 built-ins.
Hi Allen, perhaps I misunderstood. But I thought that as of ES6, O.p.toString can't be used for reliable brand checking of anything, including legacy ES<=5 built-ins. Not so? How would I do such a check of a legacy built-in in ES6?
On 11/1/2013 4:29 PM, Mark S. Miller wrote:
Hi Allen, perhaps I misunderstood. But I thought that as of ES6, O.p.toString can't be used for reliable brand checking of anything, including legacy ES<=5 built-ins. Not so? How would I do such a check of a legacy built-in in ES6?
In the spec for Object.prototype.toString:
'If tag is any of "Arguments", "Array", "Boolean", "Date", "Error", "Function", "Number", "RegExp", or "String" and SameValue(tag, builtinTag) is false, then let tag be the string value "~" concatenated with the current value of tag.'
I just read people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring and agree that it continues to preserve the brand checks that were reliable in ES5.
Cool!
On 11/1/2013 4:31 PM, Brandon Benvie wrote:
In the spec for Object.prototype.toString:
'If tag is any of "Arguments", "Array", "Boolean", "Date", "Error", "Function", "Number", "RegExp", or "String" and SameValue(tag, builtinTag) is false, then let tag be the string value "~" concatenated with the current value of tag.'
An interesting consequence of this is that a Proxy for any of these will
default to being "~" + target class. So
Object.prototype.toString.call(new Proxy([], {}))
is "[object
~Array]". But it seems the shipped has already sailed on Proxies being
conspicuously not interchangeable with their targets in many cases...
Actually that's incorrect. Proxies explicitly will return "Proxy" for their tag. Same problem though.
Actually that's incorrect. Proxies explicitly will return "Proxy" for their tag. Same problem though.
In what other ways the ship has sailed? At least regular objects and arrays can be faithfully interchanged I think, no? Things get complicated with Date/WeakMap/etc because of private state, but I remain hopeful a solution can be found in the ES7 timeframe (or whatever the next iteration is called).
I'm not sure about proxy returning "Proxy" as tag name. Is that a good idea? Brand feels like something that could safely transparently cross proxies.
On Nov 1, 2013, at 6:05 PM, David Bruant wrote:
In what other ways the ship has sailed? At least regular objects and arrays can be faithfully interchanged I think, no? Things get complicated with Date/WeakMap/etc because of private state, but I remain hopeful a solution can be found in the ES7 timeframe (or whatever the next iteration is called).
Note, proxies do not transparently operate on target objects that have private internal state or any sort of internal dependencies upon object identify. You can define a handler that over-rides most of the traps and make it work, but for most built-ins doing something like:
Proxy (new Date, {})
will give you an object that throws when methods of the target object are invoked upon it.
I'm not sure about proxy returning "Proxy" as tag name. Is that a good idea? Brand feels like something that could safely transparently cross proxies.
There is a note on in the ES6 draft on that Proxy case of O.P.toStirng that says: "This could be used an isProxy test. Do we really want that?" Nobody has answered that question yet? What do you mean by "band" transmitted accross proxies. ES6 has no general concept of brand.
We could handle that case by internally doing O.p.toString.cal(this.[[target]]) for the proxy case. Or we could just turn it into this.toString(). But neither of those seem particularly correct, in general.
Or we could simply not special case Proxy exotic objects and then Proxies would be handled like any other object, the value of the objects @@toStringTag property would be accessed and used to compose the toString result.
On 11/1/2013 7:13 PM, Allen Wirfs-Brock wrote:
Or we could simply not special case Proxy exotic objects and then Proxies would be handled like any other object, the value of the objects @@toStringTag property would be accessed and used to compose the toString result.
Which would result in things like "[object ~Array]". That'd probably be preferable than always returning "[object Proxy]" because at least you have the option of special casing it if you desire. I don't know though, because a Proxy for a Map would return "[object Map]", making it indistinguishable from a map yet it's still just as useless as a Proxy for a Date.
This just reminds me how cold I still am on the fact that you can't easily one-off Proxy anything that's not a plain Object, Array, or Function because of the lack of an invoke trap and every other type of built-in has private state... but I suppose this isn't really the thread for that.
On Nov 1, 2013, at 7:27 PM, Brandon Benvie wrote:
On 11/1/2013 7:13 PM, Allen Wirfs-Brock wrote:
Or we could simply not special case Proxy exotic objects and then Proxies would be handled like any other object, the value of the objects @@toStringTag property would be accessed and used to compose the toString result.
Which would result in things like "[object ~Array]". That'd probably be preferable than always returning "[object Proxy]" because at least you have the option of special casing it if you desire. I don't know though, because a Proxy for a Map would return "[object Map]", making it indistinguishable from a map yet it's still just as useless as a Proxy for a Date.
Remember, O.p.toString is not a reliable brand test for anything other than built-ins that existed prior to ES6. You should be trying to brand something defined via a proxy or any new built-in like Map.
This just reminds me how cold I still am on the fact that you can't easily one-off Proxy anything that's not a plain Object, Array, or Function because of the lack of an invoke trap and every other type of built-in has private state... but I suppose this isn't really the thread for that.
Right. Deciding what we want for O.p.toString is a much simpler problem.
On 11/1/2013 8:54 PM, Allen Wirfs-Brock wrote:
This just reminds me how cold I still am on the fact that you can't easily one-off Proxy anything that's not a plain Object, Array, or Function because of the lack of an invoke trap and every other type of built-in has private state... but I suppose this isn't really the thread for that. Right. Deciding what we want for O.p.toString is a much simpler problem.
I agree. I think the argument of "what could possibly expect either a WeakMap or a Map" is a convincing argument. The only place this breaks down is, of course, non-membrane Proxy usage. I'm willing to be convinced by a good use case where either a Map or WeakMap are interchangeable, but I don't think that exists.
What are the use cases for things like 'isGenerator'. When and why would
you need to know that an object upon which you are going to invoke the Iterator interface was/wasn't implemented by a generator.
co
is a library similar to Task.js that allows you to use ES6
generators as async / await.
It allows you to yield multiple different types of "future values" and uses polymorphic dispatch to the correct await implementation based on type checks.
Here there is a genuine use case for overloading yield to implement an async / await DSL that does the correct thing basd on the type of "future value" that you yield within the generator.
In it's implementation it uses isGenerator
and isGeneratorFunction
(
visionmedia/co/blob/master/index.js#L153 ).
I also personally use an isGenerator
function (
Raynos/gens/blob/master/index.js#L43 ) so that I can
implement the correct await semantics for the different types of "future
values" you are allowed to yield in my library gens
Le 02/11/2013 03:13, Allen Wirfs-Brock a écrit :
On Nov 1, 2013, at 6:05 PM, David Bruant wrote:
I'm not sure about proxy returning "Proxy" as tag name. Is that a good idea? Brand feels like something that could safely transparently cross proxies.
There is a note on in the ES6 draft on that Proxy case of O.P.toStirng that says: "This could be used an isProxy test. Do we really want that?" Nobody has answered that question yet? What do you mean by "band" transmitted accross proxies. ES6 has no general concept of brand.
lousy language, my mistake. I meant @@toStringTag.
We could handle that case by internally doing O.p.toString.cal(this.[[target]]) for the proxy case. Or we could just turn it into this.toString(). But neither of those seem particularly correct, in general.
Or we could simply not special case Proxy exotic objects and then Proxies would be handled like any other object, the value of the objects @@toStringTag property would be accessed and used to compose the toString result.
Or what about a third optional argument to the Proxy constructor to set the @@toStringTag?
On Nov 1, 2013, at 7:13 PM, Allen Wirfs-Brock wrote:
Note, proxies do not transparently operate on target objects that have private internal state or any sort of internal dependencies upon object identify. You can define a handler that over-rides most of the traps and make it work, but for most built-ins doing something like:
Proxy (new Date, {})
will give you an object that throws when methods of the target object are invoked upon it.
I just realized that the current specification of O.p.toString is a example of a method that has a identity dependency and hence won't work with default Proxy forwarding. As currently specified,
Proxy({}, {}).toString()
would yield "[object Proxy]" rather than "[object Object]" as you (and I) might have expected. The reason is that the default handler will lookup "toString" using the target object's [[Prototype]] chain and find the implementation in Object.prototype. But when it invokes that method the default handler will pass the Proxy object rather than the target object of the this value. Hence: [[object Proxy]].
This seems too wrong to me, but I'm not yet clear on an appropriate fix within O.p.toString.
There is a note on in the ES6 draft on that Proxy case of O.P.toStirng that says: "This could be used an isProxy test. Do we really want that?" Nobody has answered that question yet? What do you mean by "band" transmitted accross proxies. ES6 has no general concept of brand.
Note, that the Proxy proposal originally came with a Proxy.isProxy function and after various discussions (for example, esdiscuss/2011-July/015935 ) it was removed. An brand check approach that that identifies Proxies (including the current spec. for O.p.toString) is a backdoor way of implementing Proxy.isProxy. If the reasons for removing Proxy.isProxy are valid then we should be providing such a backdoor.
On Sat, Nov 2, 2013 at 10:55 AM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:
[...] If the reasons for removing Proxy.isProxy are valid then we should be providing such a backdoor.
not?
On Nov 2, 2013, at 11:25 AM, Mark S. Miller wrote:
On Sat, Nov 2, 2013 at 10:55 AM, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote: [...] If the reasons for removing Proxy.isProxy are valid then we should be providing such a backdoor.
not?
shouldn't
This keeps coming up. Last instance: mxr.mozilla.org/mozilla-central/source/dom/base/ObjectWrapper.jsm#16
We have it for
Array
usingArray.isArray()
. It is unclear why the arguments for arrays not apply to other types of objects, such as array buffers, nodes, blobs, files, etc.We could introduce something like
Object.crossGlobalInstanceOf(instance, type)
which checks @@crossGlobalBrand or some such which works for built-ins and is also usable by jQuery and the like.