这可能不是你想要的,但如果你传递一个函数而不是一个字符串到你的沙盒中,会怎么样呢?这甚至允许使用
eval
来处理源文件。
你的代码将像这样工作:
...
Sandbox.prototype.Run = function(fn){
fn.call(this);
}
var bx = new Sandbox();
bx.run(function(){
this.x = 1;
});
bx.getVar("x")
如果你想使用eval
,你只需要编写一个用于附加函数语法的函数即可。
/* source.js */
this.x = 1;
this.blah = "Hello, World!";
使用:
Sandbox.prototype.evaluate = function(src){
return eval("function(){" + src + "}");
}
bx.Run(Sandbox.evaluate(src));
bx.getVar("x") // 1
bx.getVar("blah") // "Hello, World!"
此方法还可以通过将沙盒代码对象和函数传递给函数来传递,并模拟一个全新的伪环境来使用。
编辑:我对您问题的
完美答案进行了一些研究,即:
“我能遍历在本地范围内声明的变量吗?”
答案是
否(StackOverflow)。目前看来这是JavaScript的局限性。希望像这样的东西会在新规范中出现。
我目前的想法是评估源代码,使所有var语句都进入窗口对象,然后可以通过迭代并手动添加到
Sandbox
对象中。
像这样
警告:极度简化
(function(){
var src = get_source_file();
eval(src);
iterate_over_each_newly_created_window_property(function(property, value){
bx[property] = value;
window[property] = undefined;
});
})();
编辑2:
我的想法可行=)
function Sandbox(){
return this;
}
Sandbox.prototype.run = function(src){
var before = {};
var prop;
for(prop in window){
before[prop] = true;
}
window.eval(src);
var changed = [];
for(prop in window){
if(!before[prop]){
this[prop] = window[prop];
delete window[prop];
}
}
}
var bx = new Sandbox();
bx.run("var x = 'Hello, World!';");
alert(bx.x);
一个工作示例(jsFiddle)
function Sandbox(){
this.keys = [];
this.values = [];
return this;
}
Sandbox.prototype.eval = function(src){
var before = {}, prop, fn;
src = "function(" + this.keys.join(",") + "){" + src + "}";
src = src.replace(/var/g, "");
for(prop in window){
before[prop] = true;
}
fn = window.eval(src);
fn.apply(window, this.values);
for(prop in window){
if(!before[prop]){
this.keys.push(prop);
this.values.push(window[prop]);
this[prop] = window[prop];
delete window[prop];
}
}
}
var bx = new Sandbox();
bx.eval("var x = 1;");
bx.eval("var y = x;");
alert(bx.x);
alert(bx.y);
编辑3:修复了错误按照您的规格要求
现在我知道它里面有漏洞和一些可能会使它失控的功能。现在轮到你来清理代码以实现真正的使用了。我向您概述了如何完成这项工作。