Nota: questo è ancora un work in progresso e in parte ispirato allo snippet di codice di Squint.
function quarantinedFunction(fnText){
var exceptionKeys=[
"eval","Object", //need exceptions for this else error. (ie, 'Exception: redefining eval is deprecated')
"Number","String","Boolean","RegExp","JSON","Date",
];
var forbiddenKeys=[
"fn","fnText","forbiddenKeys","exceptionKeys","empty","oForbiddenKeys",
];
var oForbiddenKeys=Object.create(null);
var empty=Object.create(null);
Object.freeze(empty);
forbiddenKeys.forEach(function(key){
oForbiddenKeys[key]=null;
});
[this,self].forEach(function(obj){
Object.getOwnPropertyNames(obj).forEach(function(key){
if(!key.match(/^[\$\w]+$/))return;
oForbiddenKeys[key]=null;
});
});
exceptionKeys.forEach(function(key){
delete oForbiddenKeys[key];
});
if(0){//debugging.
return function(){
return Object.keys(oForbiddenKeys);
return Object.keys(empty);
};
}
fnText=[
'"use strict";',
"var "+Object.keys(oForbiddenKeys).join(", ")+";",
"{",
fnText,
"}"
].join("\n");
var fn= (function(){
with(empty)
{
return new Function("self","window",fnText);
}
})();
return function(){
return fn.call(Object.create(null)); //self,window undefined
return fn.call(empty,empty,empty); //self,window are objects w/o properties
};
}
risultati di output (da Firefox scartafaccio):
quarantinedFunction("return location.href;")();
/*
Exception: location is undefined
*/
quarantinedFunction("someGlobalVar=15;")();
/*
Exception: assignment to undeclared variable someGlobalVar
*/
quarantinedFunction("return 9*9;")();
/*
81
*/
quarantinedFunction("return console;")();
/*
undefined
*/
E un jsfiddle con alcuni risultati.
Nota: alcuni risultati imprevisti vengono visualizzati nel violino ma non in altri strumenti (ad es.la variabile location
restituisce l'URL della pagina quando il violino viene visualizzato da firefox aurora, ma non su chrome né sullo scratchpad devtool - probabilmente il meccanismo di Firefox __noSuchMethod__
o simile 'late-binding', con conseguente aggiunta di proprietà solo quando si accede).
Stai provando a sandbox 'eval'd/codice arbitrario? C'è un modo migliore in giro se questo è il tuo obiettivo. –
No, stavo solo pensando di proteggere lo scope globale dal codice utente. Questo mi ha portato a questa domanda, riguarda la teoria. – kol
Quindi, nei browser moderni, teoricamente, si poteva [congelare] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) l'oggetto 'window'. Anche se non l'ho mai provato. –