繁体   English   中英

如何使用javascript eval防止意外的全局名称空间污染?

[英]How do I prevent accidental global name space pollution with javascript eval?

我正在用JavaScript编写一个简单的REPL(读取,评估,打印,循环)实现。 我可以隔离代码并调用上下文,如下所示:

var sandbox = {
  // Allow the input code to use predefined helper functions
  // without the preceding use of the this keyword.
  helper_fn: function() { alert("foo"); }
};

var func = new Function("with (this) { " + user_inputed_code + " }");
func.call(sandbox);

现在它关闭user_inputed_code使this参照网址到sandbox ,如果输入的代码访问或变异this很影响sandbox

但是,我注意到如果插入的代码意外忘记用关键字var作为变量赋值的序言,那么全局命名空间会被污染。

反正有没有阻止这个? 如果是这样(也许是正则表达式?)? 有没有更好的方法来解决这个问题?

我将提供两种完全不同于其他人在此讨论的方法。 它们都很激烈,并且在您想要相对隔离环境时非常有用。

  • 适用于所有浏览器的最简单技术可能是创建一个iframe,并为其添加脚本标记。 (注意,如果他们在同一个域中,至少在旧浏览器中,真的过于热心的iframe仍然可以超越它)。 我在这个问题上讨论过。
  • 使用web Workers,默认情况下具有隔离环境,并且无法访问主执行线程的全局对象。 在这个问题上讨论

更具体地说,如果您正在构建REPL,请查看我们讨论的这个答案 ,并解释如何使用iframe的第一种方法在同一范围内但在全局范围之外评估代码。

(我假设一个浏览器,在节点中你可以简单地使用vm模块并在runInContext中选择上下文)

事实证明,有一种方法是"use strict"而没有Object.freeze 您必须使用自己的沙箱对象手动替换全局命名空间:

var sandbox, module, func, output;
// Empty object or with defined methods / properties
// you want to expose as globals.
sandbox = {};
// A reference to an object you WANT to provide safe
// access to. In this example it's just an empty object.
module = {};
// A better version of eval:
func = new Function("module", "with(this){return(function(module,global,window){\"use strict\";return eval(\"" + code + "\");})(module,this,this)}");
output = func.call(sandbox, module);

此代码允许全局和窗口引用沙盒对象而不是全局名称空间。 它伪装变量globalwindow作为沙箱对象,如果输入错过了var的使用,使用"use strict"将导致它抛出异常。 它还将函数包装在with语句中,以使沙箱对象中定义的方法和属性工作,就像它们之前一样this. 要查看实现示例(带有测试规范),请查看此要点

谢谢大家的意见。 希望这个答案能帮助别人。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM