Fixing instanceof (Array.isArray() etc.)?
Axel Rauschmayer wrote:
This JavaScript pitfall is still mind-boggling to me. It is clear what happens (each frame has a different copy of Array etc.), but I find it hard to wrap my mind around the consequences in practice. Is there a plan on how to make this less painful in the long run? Initially, a cross-frame version of instanceof might help (as opposed to Function.isFunction, Date.isDate, RegExp.isRegexp etc.).
Inspired by Smalltalk messages like #isInteger (defined in Object as returning false, defined in Integer as returning true) one possible solution would be to use variation of it. Its problem (or advantage, as one sees at it) is that it is designed for overwriting and possibility have forest, not only tree of objects that return isXxx as true; the is, for duck-typing. But if recent discussion of read-only inheritance proves true, then it can be protected by defining isArray property on (every) Object.prototype as non-writable, non-configurable, value:false, and similar one with value:true on (every) Array.prototype so one can not shadow it by mere assignment, but only by (explicit or implicit) defineProperty.
From the point of security, it is probably too liberal. :-(
with postMessage and other standard/secure ways to pass data around the cross frame problem is slowly disappearing unless it's meant to sandbox the Array, as example, of that frame.
A classic example is indeed the freedom to extend the way we like a sandboxed Array which hopefully will never interferes with others defined elsewhere, either Array public static methods or those attached to the prototype.
If I define Array.prototype.doMyStuff in my frame I don't want to affect external environment anyhow plus if the top frame performs an instanceof check against my Array, and the result is true, I may expect that frame to execute my doStuff method which may points to sandboxed, private, properties I don't want other frames to access or change in untrusted code.
Array.isArray is OK for Array like objects so that we know that common operation are allowed while instanceof should act exactly as it does now so no confusion cross frame will be possible.
Same function/constructor in two different worlds aren't same thing because of the different surrounding world ... same is for Array.isArray unable to grant that object is inheriting the prototype I have enriched in that frame.
If I want to be sure an Array comes from my world, instanceof is what I need ... if I want to be sure I can use at least native methods in a generic Array with unknown origin, Array.isArray is the way to go.
If instanceof acts like Array.isArray we'll end up with less control and more error prone logic in our applications.
br
Duck typing is an interesting consideration. If one could express
x follows ArraySpec
then that would work for both array-like objects and Array instances from other frames.
On Jan 20, 2012, at 19:28 , Herby Vojčík wrote:
Inspired by Smalltalk messages like #isInteger (defined in Object as returning false, defined in Integer as returning true) one possible solution would be to use variation of it. Its problem (or advantage, as one sees at it) is that it is designed for overwriting and possibility have forest, not only tree of objects that return isXxx as true; the is, for duck-typing.
-- Dr. Axel Rauschmayer axel at rauschma.de
home: rauschma.de twitter: twitter.com/rauschma blog: 2ality.com
with postMessage and other standard/secure ways to pass data around the cross frame problem is slowly disappearing unless it's meant to sandbox the Array, as example, of that frame.
A classic example is indeed the freedom to extend the way we like a sandboxed Array which hopefully will never interferes with others defined elsewhere, either Array public static methods or those attached to the prototype.
If I define Array.prototype.doMyStuff in my frame I don't want to affect external environment anyhow plus if the top frame performs an instanceof check against my Array, and the result is true, I may expect that frame to execute my doStuff method which may points to sandboxed, private, properties I don't want other frames to access or change in untrusted code.
Makes sense. If this kind of issue went away, that would be great!
Array.isArray is OK for Array like objects so that we know that common operation are allowed while instanceof should act exactly as it does now so no confusion cross frame will be possible.
Note: Array.isArray() in general returns false for array-like objects:
$ (function () { return Array.isArray(arguments) }()) false
Axel Rauschmayer <mailto:axel at rauschma.de> January 21, 2012 10:13 PM Duck typing is an interesting consideration. If one could express
x follows ArraySpec
then that would work for both array-like objects and Array instances from other frames.
You're talking about contracts here. Not ready for standardization, but see
This JavaScript pitfall is still mind-boggling to me. It is clear what happens (each frame has a different copy of Array etc.), but I find it hard to wrap my mind around the consequences in practice. Is there a plan on how to make this less painful in the long run? Initially, a cross-frame version of instanceof might help (as opposed to Function.isFunction, Date.isDate, RegExp.isRegexp etc.).