隔离JavaScript的执行

时间:2012-04-29 22:39:29

标签: javascript plugins module isolation

最让我烦恼的一个限制是隔离代码执行能力差。

我希望能够控制执行代码的上下文,实现与Script.createContext& node.js中的Script.runInContext确实(节点正在使用绑定到V8引擎,因此我无法模拟它们的实现)。

以下是我想隔离代码执行的一些原因:

  1. 从全局命名空间(window对象和DOM)中隔离代码,但是我需要能够在必须执行同步的上下文中公开的对象上引用函数调用这使得使用WebWorker进行隔离几乎是不可能的。
  2. 通过隔离代码的执行,还可以在不再需要时释放其定义(内存管理)。
  3. 我知道可以通过将脚本加载到iframe来实现部分隔离执行,但这种方法非常繁重并且为DOM的第二个实例使用了大量内存,这对于我来说是不需要的试图做。

    我需要共享构造函数定义以及在必须在主UI线程上运行的隔离容器/上下文之间共享的对象定义。主要是我想使用这些隔离的容器来托管插件/模块(迷你应用程序),每个插件/模块通过在他们自己的Context2D对象上调用绘图命令来呈现并动态更新视口。

    如果这些容器没有在主UI线程上运行,那么代理ctx.measureText()ctx.drawImage()之类的调用将会非常困难,因为无法在{{}}中创建图像对象{1}}。

    有人知道未来的规范会使这成为可能吗?

    是否有可用于实现此目的的当前(隐藏)浏览器端API?

    是否可以更好地利用像Goggle的Dart VM这样的虚拟机并重新实现我当前的代码库? 我目前的代码库略高于20 000行代码。

    在*

    中重新实施框架会更好吗?

5 个答案:

答案 0 :(得分:3)

您可以使用简单的自执行函数对象将代码与全局命名空间隔离开来:

(function() {
   // all your code goes here
   // nobody outside of your code can reach your top level variables here
   // your top level variables are not on the window object

   // this is a protected, but top level variable
   var x = 3;

   // if you want anything to be global, you can assign it to the window object.
   window.myGlobal = {};

   function myTopLevelFunction(x,y,z) {
       // code here
   }

})();

如果你想拥有这些执行上下文中的多个并且能够在它们之间共享,那么你将不得不通过一个公知的位置,一个真正的全局变量或一个已知DOM对象上的属性或类似的东西进行会合。那。声明一个全局命名空间对象并使用属性来访问您在模块之间共享的内容是相对常见的。我知道它并不完全完美,但它确实有效。以下是使用单个全局命名空间对象进行渲染的示例:

// module AAA
(function() {
   // module AAA code goes here

   // set up global namespace object and whatever references we want to be global
   window.myModuleTop = window.myModuleTop || {};
   myModuleTop.AAA = {};
   myModuleTop.AAA.myFuncA = function() {};

})();


// module BBB
(function() {
   // module BBB code goes here

   // set up global namespace object and whatever references we want to be global
   window.myModuleTop = window.myModuleTop || {};
   myModuleTop.BBB = {};
   myModuleTop.BBB.myFuncB = function() {};

})();

答案 1 :(得分:3)

我见过的最近的图书馆是Caja

基本上,在非严格的javascript代码中,有很多方法可以访问全局对象(浏览器中的window),使真正的隔离成为一个非常棘手的问题。 Caja做了一些iframing技巧来修补它,但说实话,我不确定它是如何工作的。

答案 2 :(得分:1)

“标准”命名空间是一个选项吗?像:

var myNamespace = {};

myNamespace.myFunc = function() { return true; }

这种方法是我能想到的最简单的方法,可能是许多问题的解决方案。虽然不是真正的沙盒,但它可以让代码更不容易出错。

答案 3 :(得分:0)

你不能像上面提到的其他答案那样使用闭包,然后使用阴影dom来确保用户无法进入dom的其余部分吗?像这样:

var containerNode = someDomNode
var root = containerNode.createShadowRoot()
;(function(root){
  var window = null, document = null, history = null,
      screen = null, navigator = null, location = null

  // isolated code goes here

})(root)

警告:

  • 如果在隔离代码的上下文之外创建其他全局对象,则需要像使用窗口,文档等那样显式地隐藏变量,否则隔离的代码将访问它。
  • 除非您的孤立代码根本不需要与dom进行交互,否则在浏览器中不会有明显的阴影效果。
  • 您必须非常小心,您所做的对象提供隔离代码访问权限并不包含对您 想要它的内容的引用有权访问。有时这很容易发生。
  • 我之所以提出这个建议,是因为它可行,但我不知道是否还有其他办法来获取窗口和文档对象之类的东西。

答案 4 :(得分:0)

有一个proposal for Realms API,似乎可以解决类似的问题。仍在讨论中,但是已经有一个polyfill-realms-shim