Update: Since this is unanswered, I'm changing the question slightly. Comments on the post on Dean's blog linked below indicate this technique does not work in Safari.
My question now is: does the technique described below work* in modern browsers, and in particular can someone confirm whether it works in Safari?
Here's a more recent blog post. It says at one point:
Sandboxed natives ... are supported in a variety of browsers, including ... Safari 2.0+
...but later says that the iframe technique is "supported by all major browsers except Safari," and the fallback he shows involves doing some weird stuff with faked constructors and __proto__
that seems a bit hacky.
I almost find it hard to believe that two different windows could actually share the same, say, Object.prototype. What happens with cross-domain iframes? If I modify prototypes in one frame, do the prototypes in the other frame get modified? This seems like an obvious security concern. Someone please shed some light on this situation.
* By "work" I mean My.Object != Object
, so the prototypes can be modified in one window without affecting the other.
Original post
I know this has been asked before, but I have a specific solution in mind, and I want to know if this type of solution has been discussed before and where I might learn how reliable and well-accepted it is.
The question is how to extend native types in javascript without actually messing with the types themselves, so just altering Array.prototype is no good (maybe other code is using for..in with arrays). Creating a fake constructor that returns a native array with some functions tacked on doesn't seem like a good solution either, actually extending the native objects seems better. But you can't do the normal javascript dummy function prototype switcharoo style extension with native types either, because you'll get errors like "push is not generic" when you try to call native functions.
So, the solution I have in mind works like this: create another window, add functionality to prototypes of native constructors in that window, and use those constructors in your program.
This example extends Array
as My.Array
with an each
function and String
as My.String
with an alert
function.
var My = (function(){
// create an iframe to get a separate global scope
var iframe = document.createElement('iframe');
iframe.style.height = '0px';
iframe.style.width = '0px';
iframe.style.border = 'none';
iframe.style.position = 'absolute';
iframe.style.left = '-99999px';
document.documentElement.appendChild(iframe);
var My = iframe.contentWindow;
My.String.prototype.alert = function(){
alert(this);
}
My.Array.prototype.each = function(callback){
for (var i=0, l=this.length; i<l; i++) {
callback(this[i], i);
}
}
return My;
}());
Again, my question is whether this approach has been discussed before, what it's called, where I can find more information, etc. I'd like to know if there is a cleaner way to get another global scope without using an iframe, or if it's possible this will fail for some reason in certain javascript engines, or if anyone thinks it's a particularly bad idea or whatever.
Update: I guess people are calling this kind of thing an iframe sandbox, not to be confused with the HTML5 iframe sandbox attribute.
related:
http://dean.edwards.name/weblog/2006/11/hooray/
http://webreflection.blogspot.com/2008/03/javascript-arrayobject.html