Reputation: 42736
Say you have the following code:
var something = "here";
function test(){
console.log(something)
}
Obviously when you call test()
, the console log will show here
as it will go up through the scope chain till it finds something
or reaches the end of the chain. But is there a way to clear out the scope chain so that it does not look for variables outside the local scope.
I know you can use with
, when not using strict mode, to add to the scope chain, so is there a way to do the opposite, remove scopes from the chain or some other way to make outer scopes inaccessible.
The closest thing I could think of that would accomplish this would be to pass the function body to a web worker along with any arguments, and execute it in the worker and have the results messaged back. And of course that's extra overhead and a bit over complicated to achieve something like this.
Do not actually need this, or have a situation in mind of its use, but thought it would be interesting to see if it was possible or not.
Upvotes: 3
Views: 120
Reputation: 42736
As said in the question, the only way of I thought of doing this was with web workers. Jeremy J Starcher mentioned in the comments about using an iframe, which I didn't even think of till the mention. So an example of that is provided as well.
Main javascript
(function(window){
'use strict';
function respond(oEvent){
this.cb&&this.cb(oEvent.data);
this.worker.terminate();
}
window.sandbox = function(fn){
return function(){
var worker = new Worker("sandboxWorker.js");
worker.onmessage = respond.bind({
worker:worker,
cb:[].pop.call(arguments)
});
worker.postMessage({
"fn":fn.toString(),
"args":[].slice.call(arguments,0)
});
};
};
})(window);
sandboxWorker.js
onmessage = function (oEvent) {
var fn = eval("("+oEvent.data.fn+")");
var res = fn.apply(null,oEvent.data.args);
postMessage(res);
};
Test
//Assume jQuery has been included
function maliciousAdd(a,b){
jQuery = function(){ alert("No it doesn't fix everything"); }
return a+b;
}
var sandBoxed = window.sandbox(maliciousAdd);
sandBoxed(1,2,function(result){
jQuery(document.body).css("background","#3F3");
console.log(result);
});
postMessage
would have to be usedJavascript: modified to use Function
to generate inner sandbox function as suggested by Felix Kling
window.onload = function(){
var frame = document.createElement("iframe");
frame.src = "";
frame.style.display = "none";
window.document.body.appendChild(frame);
var win = (frame.contentWindow) ? frame.contentWindow : (frame.contentDocument.document) ? frame.contentDocument.document : frame.contentDocument;
window.sandbox = function(fn){
return function(){
var args = [].slice.call(arguments);
win.location.reload();
win.sandbox = win.Function(
'fn','args',
'fn = eval("("+fn+")"); return fn.apply(this,args);'
);
win.document.head.appendChild(script);
return win.sandbox(fn.toString(),args);
};
};
};
Upvotes: 3