【问题标题】:Create a variable and execute code inside a Sandbox在沙箱中创建变量并执行代码
【发布时间】:2011-08-11 01:19:07
【问题描述】:

如何管理它以通过 Run() 在 Sandbox() 中放置变量和运行代码?

function Sandbox() {
    this.test = 'insandbox';
}

Sandbox.prototype.Run = function(src) {
    eval.call(this, src);
};

Sandbox.prototype.getvar = function(name) {
    return this[name];
};

var bx = new Sandbox();
bx.Run('var x = 1;');
print(bx.getvar('test'))
print(bx.getvar('x'))        // undefined
print(x)

请不要回答有关 eval() 不安全的问题,我不应该使用它。 请不要回答有关使用 setter/getter 的问题。

感谢阅读!

【问题讨论】:

  • 我认为你的范围有误

标签: javascript


【解决方案1】:

这可能不是您要查找的内容,但如果不是将字符串传递给您的沙箱,而是传递一个函数会怎样。这甚至允许将eval 用于源文件。

您的代码将像这样工作:

...

Sandbox.prototype.Run = function(fn){
    fn.call(this);
}

var bx = new Sandbox();
bx.run(function(){
    this.x = 1;
});
bx.getVar("x") // 1

如果你想使用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!"

同样使用此方法,您可以将沙盒代码对象和函数传递给要使用的函数,该函数将模拟一个全新的伪环境以供使用。

编辑:我对您的问题的完美答案做了一些研究,即

我可以遍历在本地范围内声明的变量吗?

答案是no (StackOverflow)。目前看来这是javascript的限制。希望新规范中会出现类似的内容。

我目前的想法是评估源以使所有 var 语句都转到 window 对象,通过一些努力,可以迭代并添加到 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){
    // Take a snapshopt of the window object before
    var before = {};
    var prop;
    for(prop in window){
        before[prop] = true;
    }
    // Then evaluate the source
    window.eval(src);
    // Then see what changed
    var changed = [];
    for(prop in window){
        if(!before[prop]){
            // Add to the sandbox object
            this[prop] = window[prop];
            delete window[prop];
        }
    }
}
var bx = new Sandbox();
bx.run("var x = 'Hello, World!';");
alert(bx.x);

A working example (jsFiddle)

function Sandbox(){
this.keys = [];
this.values = [];
    return this;
}
Sandbox.prototype.eval = function(src){
    var before = {}, prop, fn;
    // Take a snapshopt of the window object before
    src = "function(" + this.keys.join(",") + "){" + src + "}";
    src = src.replace(/var/g, "");
    /* I'm not a wisard at regex so a better one should be used avoid this bug
    var x, y, z; */
    for(prop in window){
        before[prop] = true;
    }
    // Then evaluate the source
    fn = window.eval(src);
    fn.apply(window, this.values);
    // Then see what changed
    for(prop in window){
        if(!before[prop]){
            // Add to the sandbox object
            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:修复错误 to your specifications

现在我知道其中存在错误以及一些可能使其失控的功能。现在,清理代码以供实际使用是您的工作。我从概念上给了你如何做到这一点。

【讨论】:

  • 这不是我在我的情况下可以使用的,但感谢您的支持!
  • 不,这些变量应该放在 Sandbox 对象中。
  • 这还不错! :-) 我只是想用 with() 来达到这个目的。我会定义的。看看那个方法,也许我们可以再微调一下。我不喜欢那个 window.eval() ;-)
【解决方案2】:

这应该可行:

...

Sandbox.prototype.run = function(src) {
    eval(src);
};

...

bx.run('this.x = 1;');

...

【讨论】:

  • bx.getvar('x') 将导致未定义。我不想在 Run() 的表达式中使用“this”。
  • 如果你想让它工作,你需要使用thisvar 创建一个与 Sandbox 的实例无关的局部变量。
  • 是的,这行得通。谢谢你。但是我不能将它添加到每个表达式中,因为我不知道 Run() 每次都使用哪种确切的表达式。
  • 但是不可以设置一个局部变量,使用getvar()返回局部变量吗?
  • 不,局部变量的作用域一结束就消失了。而且该范围不是getvar 方法的一部分。
【解决方案3】:

你可以使用闭包

Sandbox.prototype.Run = function(src) {
    (function(_src){
        eval.call(this, _src);
    })(src);
};

【讨论】:

  • eval 只能在全局范围内运行。这是 javascript 的限制。
猜你喜欢
  • 2010-09-24
  • 1970-01-01
  • 1970-01-01
  • 2015-05-16
  • 1970-01-01
  • 2010-12-15
  • 2011-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多